Hey guys, this is my first time doing serial and I need another set of eyes.
I connected a PCA9685 board to the Arduino and to that I have 5V coming from my power supply, and 6 servo motors all connected into a 3D printed robot arm.
The first issue I had when connecting 6 Pots, were that the PCA9685 shares the A4 & A5 ports so I only have 4 connections to work with. (My ARDUINO MEGA 2560 is on it's way).
In the meantime I thought I'd try controlling the Arduino's servos with Processing from my PC, so I connected it all up through the serial port but it's slow.
Here is how my program should work:
Button is pressed in Processing and a string is sent through the serial port -> 0:90\n
Servo 0 : position 90 and the end of line.
First char is the servo number 0 - 5, a colon then the position.
The Arduino takes the string apart and runs the servo. This all works but it lags a lot so I tried putting in a multiplier and adding that. Still slow.
Here is my code:
PROCESSING
import processing.serial.*;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
boolean down = false;
boolean bover = false;
// Multiplier
int inc0 = 10;
int inc1 = 10;
int inc2 = 10;
int inc3 = 10;
int inc4 = 10;
int inc5 = 10;
// Buttons
Button bUp0, bDn0, bUp1, bDn1, bUp2, bDn2, bUp3, bDn3, bUp4, bDn4, bUp5, bDn5, bReset;
// Init value for servo numbers
int num0 = 90;
int num1 = 140;
int num2 = 50;
int num3 = 100;
int num4 = 110;
int num5 = 140;
void setup() {
size(650, 400);
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 500000); // I tried several speeds which make no difference
textSize(24);
fill(0, 80, 150);
// Buttons
bUp0 = new Button(25, 25, 100, 50, "Up 0");
bDn0 = new Button(25, 125, 100, 50, "Down 0");
bUp1 = new Button(125, 25, 100, 50, "Up 1");
bDn1 = new Button(125, 125, 100, 50, "Down 1");
bUp2 = new Button(225, 25, 100, 50, "Up 2");
bDn2 = new Button(225, 125, 100, 50, "Down 2");
bUp3 = new Button(325, 25, 100, 50, "Up 3");
bDn3 = new Button(325, 125, 100, 50, "Down 3");
bUp4 = new Button(425, 25, 100, 50, "Up 4");
bDn4 = new Button(425, 125, 100, 50, "Down 4");
bUp5 = new Button(525, 25, 100, 50, "Up 5");
bDn5 = new Button(525, 125, 100, 50, "Down 5");
bReset = new Button(25, 200, 100, 50, "Reset");
}
void draw() {
background(204);
text(num0, 50, 110);
text(num1, 150, 110);
text(num2, 250, 110);
text(num3, 350, 110);
text(num4, 450, 110);
text(num5, 550, 110);
bUp0.update();
bDn0.update();
bUp1.update();
bDn1.update();
bUp2.update();
bDn2.update();
bUp3.update();
bDn3.update();
bUp4.update();
bDn4.update();
bUp5.update();
bDn5.update();
bReset.update();
// Button clicks
if (bUp0.clicked) {
num0 = num0 + inc0;
myPort.write("0:" + num0 + "\n");
}
if (bDn0.clicked) {
num0 = num0 - inc0;
myPort.write("0:" + num0 + "\n");
}
if (bUp1.clicked) {
num1 = num1 + inc1;
myPort.write("1:" + num1 + "\n");
}
if (bDn1.clicked) {
num1 = num1 - inc1;
myPort.write("1:" + num1 + "\n");
}
if (bUp2.clicked) {
num2 = num2 + inc2;
myPort.write("2:" + num2 + "\n");
}
if (bDn2.clicked) {
num2 = num2 - inc2;
myPort.write("2:" + num2 + "\n");
}
if (bUp3.clicked) {
num3 = num3 + inc3;
myPort.write("3:" + num3 + "\n");
}
if (bDn3.clicked) {
num3 = num3 - inc3;
myPort.write("3:" + num3 + "\n");
}
if (bUp4.clicked) {
num4 = num4 + inc4;
myPort.write("4:" + num4 + "\n");
}
if (bDn4.clicked) {
num4 = num4 - inc4;
myPort.write("4:" + num4 + "\n");
}
if (bUp5.clicked) {
num5 = num5 + inc5;
myPort.write("5:" + num5 + "\n");
}
if (bDn5.clicked) {
num5 = num5 - inc5;
myPort.write("5:" + num5 + "\n");
}
// This sends 0:0 which the Arduino knows to reset the arm to its default position
if (bReset.clicked) {
num0 = 90;
num1 = 140;
num2 = 50;
num3 = 100;
num4 = 110;
num5 = 140;
myPort.write("0:0\n");
}
}
class Button {
int xpos, ypos, wid, hei;
int colorUp = 255;
int colorOver = 100;
int colorDown = 200;
String text;
boolean over = false;
boolean down = false;
boolean clicked = false;
Button(
int tx, int ty,
int tw, int th,
String tlabel
) {
xpos = tx;
ypos = ty;
wid = tw;
hei = th;
text = tlabel;
}
void update() {
//it is important that this comes first
if (down && over && !mousePressed) {
clicked=true;
} else {
clicked=false;
}
if (mouseX > xpos && mouseY > ypos && mouseX < xpos + wid && mouseY < ypos + hei) {
over=true;
if (mousePressed) {
down=true;
} else {
down=false;
}
} else {
over=false;
}
smooth();
fill(colorUp);
if (!over) {
fill(colorUp);
} else {
if (!down) {
fill(colorDown);
} else {
fill(0, 100, 230);
}
}
stroke(0);
rect(xpos, ypos, wid, hei, 10); //draws the rectangle, the last param is the round corners
fill(0);
textSize(24);
text(text, xpos+wid/2-(textWidth(text)/2), ypos+hei/2+(textAscent()/2));
//all of this just centers the text in the box
}
}
ARDUINO
// Include Wire Library for I2C Communications
#include <Wire.h>
// Include Adafruit PWM Library
#include <Adafruit_PWMServoDriver.h>
// For the servos
#define MIN_PULSE_WIDTH 650
#define MAX_PULSE_WIDTH 2350
#define FREQUENCY 50
// Calculate based on max input size expected for one command
#define INPUT_SIZE 30
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
void setup() {
Serial.begin(500000);
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
// Setup motor board
pwm.begin();
pwm.setPWMFreq(FREQUENCY);
}
void loop() {
GetData();
}
void DoCommand(int servoId, int position)
{
// Do something with servoId and position
//Serial.print("servoId "); Serial.print(servoId);
//Serial.print(" - position "); Serial.println(position);
if (servoId == 0 && position == 0) {
moveMotor(0, 90);
moveMotor(1, 140);
moveMotor(2, 50);
moveMotor(3, 100);
moveMotor(4, 110);
moveMotor(5, 140);
}
else
{
moveMotor(servoId, position);
}
}
void moveMotor(int motorOut, int position)
{
int posMapped, pulse_width;
// Convert to pulse width
posMapped = map(position, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
pulse_width = int(float(posMapped) / 1000000 * FREQUENCY * 4096);
//Control Motor
pwm.setPWM(motorOut, 0, pulse_width);
}
// This gets the data and splits up the values
void GetData() {
// Get next command from Serial (add 1 for final 0)
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
// Add the final 0 to end the C string
input[size] = 0;
// Read each command pair
char* command = strtok(input, "&");
while (command != 0)
{
// Split the command in two values
char* separator = strchr(command, ':');
if (separator != 0)
{
// Actually split the string in 2: replace ':' with 0
*separator = 0;
int servoId = atoi(command);
++separator;
int position = atoi(separator);
// Do something with servoId and position
DoCommand(servoId, position);
}
// Find the next command in input string
command = strtok(0, "&");
}
}