Serial Control of Servo Motor

Hi All,

Long time reader, first time poster. I have a question in regard to serial communication from Max MSP to Arduino which controls some servo motors. (I am also going to post the same question in the MAX forum)

I have tested the Max patch serial output and it is reading correctly (in the 'Max Window'). When I then use it with Arduino, I can see the TX/TR LED's flash when a number has been output. However, when I add the final component, the servo, it doesn't want to work/move.

To give some context, I have a matrix in Max with 4 rows and 32 columns. Each row is assigned a 'bit number' for the purposes of communicating to a specific servo. when the patch is run, each time a highlighted matrix point is passed, it sends the assigned 'bit number' out of the serial port.

Arduino then reads the 'bit number' and goes through it's code and sends it to the specific pin to move the servo motor.

When I use the serial monitor with Arduino and send the bit number manually, the servo moves.

Example of code below using 'bit number' 120 as dummy number and moving the servo to 45 degrees and then back to Zero. (virtually tested using TinkerCAD (manual number assignment))

#include <Servo.h>

Servo myServo;

int pos = 45;

int incomingByte = 0;

void setup() {
  Serial.begin(9600);
  myServo.attach(9);
  myServo.write(0);
}

void loop() {
  for(pos = 0; pos <= 45; pos += 1)
    if(Serial.available()) {
      int incomingByte = Serial.parseInt();
      if(incomingByte == 120) {
        myServo.write(pos);
        delay(1000);
        myServo.write(0);
        delay(1000);
      }
    }
}

Any thoughts or suggestions would be greatly appreciated!

Thanks All and keep up the great work!

The for loop runs continuously even when there is no Serial input, so when pos is written to the servo it could be any value between 0 and 45

That is presumably not what you want

Thank you for the response UKHeliBob.

So changing my for condition to something like

for(pos = 45; pos += 1) 

It would essentially tell the motors to turn 1 degree at a time to 45 and back?

Or am i missing something here?

I want the servos to remain at 0 position, and when the bit number is heard by serial, turn to 45 degrees and back to 0 and wait for serial input.

Thanks again for the reply!

Then why do you need a for loop ?

void loop()
{
  if (Serial.available())
  {
    int incomingByte = Serial.parseInt();
    if (incomingByte == 120)
    {
      myServo.write(45);
      delay(1000);
      myServo.write(0);
      delay(1000);
    }
  }
}

Thanks again for the reply.

:man_facepalming: so simple.

I have just tested virtually using TinkerCAD with multiple servo's and it is pretty much doing what I want it too. Now it's just thinhs like speed and how quick the servo can read the data and react. But that is not part of this thread and something I will try to figure out myself before asking for help.

You never learn unless you try!

Thank again!

Hi All,

I thought I would post an update on my progress for future readers and for interest purposes.

I haven't yet tested this with Max, however it is working when I test it virtually.

After reading some of the Arduino reference and looking at other forum topics I have adapted the code.

#include <Servo.h>

Servo myServo, myServo2, myServo3;

int pos = 45;

char incomingByte;

boolean newData = false;

void setup() {
  Serial.begin(115200);
  myServo.attach(9);
  myServo.write(0);
  myServo2.attach(10);
  myServo2.write(0);
  myServo3.attach(11);
  myServo3.write(0);
  Serial.println("Born and ready for action");
}

void loop() {
  recvData();
  moveServo();
}

void recvData() {
  if(Serial.available() > 0) {
    incomingByte = Serial.read();
    newData = true;
  }
}

void moveServo() {
    if(incomingByte == 50 && newData == true) {
        Serial.println(incomingByte);
        myServo.write(pos);
        delay(150);
        myServo.write(0);
        delay(150);
        		
      newData = false;
    }
  	if(incomingByte == 51 && newData == true) {
        Serial.println(incomingByte);
        myServo2.write(pos);
        delay(150);
        myServo2.write(0);
        delay(150);
        		
      newData = false;
    }
  	if(incomingByte == 52 && newData == true) {
        Serial.println(incomingByte);
        myServo3.write(pos);
        delay(150);
        myServo3.write(0);
        delay(150);
        		
      newData = false;
    }
  }