Control servos using sliders

I’m trying to write Processing code that uses ControlP5 to create an GUI that have sliders that send values to Arduino code to control many servos. If I have four sliders called Hand, Wrist, Elbow, and Shoulder in Processing code and four servos called servo01, servo02, servo03, and servo04 in Arduino code, moving the hand slider should cause servo01 to move, wrist slider should cause servo02 to move, etc. The problem is that serial.write can’t send data to correct servo.

import processing.serial.*;
import controlP5.*;
Serial myPort; 
ControlP5 cp5;
ControlGroup messageBox;
String data = "0";
String string01;

void setup() 
{
  size(1200,800);
  myPort = new Serial(this, "COM9", 9600);
  myPort.bufferUntil('\n');
  cp5 = new ControlP5(this);
  createMessageBox();
}

void draw() 
{
  background(0);
}

void createMessageBox() 
{
  PFont myFont = createFont("Arial",16,true);
  Slider slider01 = cp5.addSlider("slider01val");
  slider01.setLabel("Left Hand");
  slider01.setSize(360,30);
  slider01.setPosition(50,50);
  slider01.setRange(0,180);
  slider01.setColorForeground(color(0,113,220));
  slider01.setColorBackground(color(255,255,255));
  slider01.setValue(0);
  slider01.setFont(myFont);
  Slider slider02 = cp5.addSlider("slider02val");
  slider02.setLabel("Right Hand");
  slider02.setSize(360,30);
  slider02.setPosition(600,50);
  slider02.setRange(0,180);
  slider02.setColorForeground(color(0,113,220));
  slider02.setColorBackground(color(255,255,255));
  slider02.setValue(0);
  slider02.setFont(myFont);

}

void controlEvent(ControlEvent theEvent) 
{
  if(theEvent.getController().getName().equals("slider01val")) 
  {
    int val01 = int(theEvent.getController().getValue());
    println("slider01 value is ",val01);
    println(3);
    //myPort.write(val);
  }
  if(theEvent.getController().getName().equals("slider02val")) 
  {
    int val02 = int(theEvent.getController().getValue());
    println("slider02 value is ",val02);
    //myPort.write(sliderval02);
  }

}

`#include <Servo.h>
Servo myServo01;
Servo myServo02;
char myServo01Channel=0, myServo02Channel=1;
char serialChar=0;
int val01 = 0;
int val02 = 0;
void setup() 
{
  myServo01.attach(3);
  myServo02.attach(4);
  myServo01.write(0);
  myServo02.write(0);
  Serial.begin(9600);
}
void loop(){
  while(Serial.available() <=0);  //Wait for a character on the serial port.
  serialChar = Serial.read();     //Copy the character from the serial port to the variable
  if(serialChar == myServo01Channel){  //Check to see if the character is the servo ID for the tilt servo
    while(Serial.available() <=0);  //Wait for the second command byte from the serial port.
    myServo01.write(Serial.read());  //Set the tilt servo position to the value of the second command byte received on the serial port
  }
  else if(serialChar == myServo02Channel){ //Check to see if the initial serial character was the servo ID for the pan servo.
    while(Serial.available() <= 0);  //Wait for the second command byte from the serial port.
    myServo02.write(Serial.read());   //Set the pan servo position to the value of the second command byte received from the serial port.
  }
  //If the character is not the pan or tilt servo ID, it is ignored.
}````

How can I fix the problems?

Hello @jeffmorris1956,

This may help get you started with the serial communication:

Start simple and build on that…

:)

One technique that I have used is to send a character along with the value, eg ‘a’ + value might be for hand, ‘b’+value might be for wrist, etc. On the Arduino end check to see which character was sent and then use ‘switch’ to send the value to the correct control. You could probably also use an array if you wanted to send all the values at one time; I’m assuming that you want to send them individually as each slider is manipulated.

1 Like

The following source code is one possible solution and demonstrates a single servo, which is all that I have to test with. If you use this technique you will have to scale it up to four servos.

Processing Code:

import processing.serial.*;
import controlP5.*;

Serial port; 
ControlP5 cp5;

int handValue = 20; // init
int val;

void setup() {
  size(600,300);
  background(0);
  printArray(Serial.list());
  port = new Serial(this, Serial.list()[2], 9600);

  cp5 = new ControlP5(this);
   
  cp5.addSlider("handValue")
    .setPosition(100, 50)
    .setSize(200,20)
    .setRange(0, 180)
    .setId(1);        
}

void draw() {  
  if(port.available() > 0) {
    val = port.read();
    println("received from Arduino: ", val);
    }  
}

void controlEvent(ControlEvent theEvent) {
  switch(theEvent.getController().getId()) {
    case(1):  // hand
    handValue = (int)(theEvent.getController().getValue());
    String handStr = str('h') + str(handValue);
    port.write(handStr);
    println("transmit hand string = ", handStr);
    break;
    case(2):  // wrist
    break;
    case(3):  // elbow  
    break;
    case(4):  // shoulder
    break;
  }
}

Arduino Code:

#include <Servo.h>

Servo servo1;
int recdValue;
int handVal;

void setup() {
  Serial.begin(9600);
  servo1.attach(9); // Connected to digital 9 (yellow), 5v (red), gnd (black)
}

void loop() {
  if ( Serial.available()) {
    int inByte = Serial.read();
    switch (inByte) {
      case 'h':  // hand
        recdValue = Serial.parseInt();
        handVal = recdValue;
        servo1.write(handVal);
        break;
      case 'w':  // wrist
        break;
      case 'e':  // elbow
        break;
      case 's':  // shoulder
        break;
    }
    Serial.write(recdValue); // Send back to Processing for verification
  }
}

Hi

With this example I could send multi sliders values to Arduino

arduino.write("a" + val1+"\n");

arduino.write("b" + val2+"\n");
arduino.write("c" + val3+"\n");
arduino.write("d" + val4+"\n");
Etc

This is the code

import controlP5.*;
import processing.serial.*;
 
ControlP5 cP5a;
ControlP5 cP5b;
 
Serial arduino;
 
void setup() {
  size(350,120);
 printArray(Serial.list());
 
  arduino = new Serial(this, Serial.list()[0], 9600);
 
  cP5a = new ControlP5(this);
  cP5a.addSlider("CYCLE_TIME", 999, 1999,999, 10, 10, 255, 35);
  cP5b = new ControlP5(this);
  cP5b.addSlider("PULSE", 55, 455, 55, 10, 55, 255, 35);
}
 
void draw()  {
  background(0);
 
  }
 
void controlEvent(ControlEvent theEvent) {
  if(theEvent.isController()) {
 
 print("control event from : "+theEvent.getController().getName());
 println(", value : "+theEvent.getController().getValue());
 
 if(theEvent.getController().getName()=="CYCLE_TIME") {
   int val1 = int(theEvent.getController().getValue());
   arduino.write("a" + val1+"\n");
 
 }
 
 if(theEvent.getController().getName()=="PULSE") {
   int val2 = int(theEvent.getController().getValue());
   arduino.write("b" + val2+"\n" );
   }
  }
}

Hi
Some examples

Hello @jeffmorris1956,

Your posted code did not seem to work for me and sharing my exploration.

I modified your code and used the Arduino code from my previous post to echo back data:

void setup() 
  {
  size(1200,800);
  myPort = new Serial(this, "COM7", 9600);
  delay(1000);          // This did the trick!
  println("Ready!");
  //myPort.bufferUntil('\n');
  cp5 = new ControlP5(this);
  createMessageBox();
  }

void draw() 
  {
  background(0);
  if(myPort.available() > 0)
    {
    int val = myPort.read();
    println("Rx: ", val);
    }
  }

Your events:

myPort.write(val01);

myPort.write(val02);

It only worked on my Arduino Mega 2560 R3 once I added the delay:

delay(1000); // This did the trick!

Related:
https://discourse.processing.org/t/processing-to-arduino-serial-library-example/11143

The correct servo part you can work on… lots of suggestions and resources out there for that.

:)

The delay(1000) might be only for Windows OS. It runs ok on a Mac. With this code:

void setup() {
  size(1200,800);
  myPort = new Serial(this, Serial.list()[2], 9600);
  myPort.bufferUntil('\n');
  cp5 = new ControlP5(this);
  createMessageBox();
}

...

This is what I see: