Hello, I have 2-Two separate codes and I am having difficulty combining them. Maybe someone could pinpoit me into a right direction. General idea is to control 4-Nema 17 Stepper Motors and 1-Servo using Arduino Uno+CNC Shield, etc. Both arduino codes and processing codes work individually. Already tested. Hardware is no issue either.
1st Arduino Code (4 Steppers):
*/
#include <AccelStepper.h>
#include <Servo.h>
#include <math.h>
// Define the stepper motors and the pins the will use
AccelStepper stepper1(1, 2, 5); // (Type:driver, STEP, DIR)
AccelStepper stepper2(1, 3, 6);
AccelStepper stepper3(1, 4, 7);
AccelStepper stepper4(1, 12, 13);
double x = 10.0;
double y = 10.0;
double L1 = 228; // L1 = 228mm
double L2 = 136.5; // L2 = 136.5mm
double theta1, theta2, phi, z;
int stepper1Position, stepper2Position, stepper3Position, stepper4Position;
const float theta1AngleToSteps = 44.444444;
const float theta2AngleToSteps = 35.555555;
const float phiAngleToSteps = 10;
const float zDistanceToSteps = 100;
byte inputValue[5];
int k = 0;
String content = "";
int data[10];
int theta1Array[100];
int theta2Array[100];
int phiArray[100];
int zArray[100];
int positionsCounter = 0;
void setup() {
Serial.begin(115200);
// Stepper motors max speed
stepper1.setMaxSpeed(4000);
stepper1.setAcceleration(2000);
stepper2.setMaxSpeed(4000);
stepper2.setAcceleration(2000);
stepper3.setMaxSpeed(4000);
stepper3.setAcceleration(2000);
stepper4.setMaxSpeed(4000);
stepper4.setAcceleration(2000);
data[5] = 0;
}
void loop() {
static int v = 0;
if (Serial.available()) {
content = Serial.readString(); // Read the incomding data from Processing
// Extract the data from the string and put into separate integer variables (data[] array)
for (int i = 0; i < 10; i++) {
int index = content.indexOf(","); // locate the first ","
data[i] = atol(content.substring(0, index).c_str()); //Extract the number from start to the ","
content = content.substring(index + 1); //Remove the number from the string
}
stepper1Position = data[2] * theta1AngleToSteps;
stepper2Position = data[3] * theta2AngleToSteps;
stepper3Position = data[4] * phiAngleToSteps;
stepper4Position = data[5] * zDistanceToSteps;
stepper1.setSpeed(data[7]);
stepper2.setSpeed(data[7]);
stepper3.setSpeed(data[7]);
stepper4.setSpeed(data[7]);
stepper1.setAcceleration(data[8]);
stepper2.setAcceleration(data[8]);
stepper3.setAcceleration(data[8]);
stepper4.setAcceleration(data[8]);
stepper1.moveTo(stepper1Position);
stepper2.moveTo(stepper2Position);
stepper3.moveTo(stepper3Position);
stepper4.moveTo(stepper4Position);
while (stepper1.currentPosition() != stepper1Position || stepper2.currentPosition() != stepper2Position || stepper3.currentPosition() != stepper3Position || stepper4.currentPosition() != stepper4Position)
{
stepper1.run();
stepper2.run();
stepper3.run();
stepper4.run();
}
}
}
void serialFlush() {
while (Serial.available() > 0) { //while there are characters in the serial buffer, because Serial.available is >0
Serial.read(); // get one character
}
}
/*
data[2] - Joint 1 angle
data[3] - Joint 2 angle
data[4] - Joint 3 angle
data[5] - Z position
data[7] - Speed value
data[8] - Acceleration value
*/
1st Processing Code (4 Steppers):
//Processing Code:
import processing.serial.*;
import controlP5.*;
import static processing.core.PApplet.*;
Serial myPort;
ControlP5 cp5; // controlP5 object
int j1Slider = 0;
int j2Slider = 0;
int j3Slider = 0;
int zSlider = 0;
int j1JogValue = 0;
int j2JogValue = 0;
int j3JogValue = 0;
int zJogValue = 0;
int speedSlider = 500;
int accelerationSlider = 500;
int positionsCounter = 0;
int saveStatus = 0;
int runStatus = 0;
int slider1Previous = 0;
int slider2Previous = 0;
int slider3Previous = 0;
int sliderzPrevious = 100;
int speedSliderPrevious = 500;
int accelerationSliderPrevious = 500;
boolean activeIK = false;
int xP=0;
int yP=0;
int zP=0;
float L1 = 228; // L1 = 228mm
float L2 = 136.5; // L2 = 136.5mm
float theta1, theta2, phi, z;
String[] positions = new String[100];
String data;
void setup() {
size(900, 900);
myPort = new Serial(this, "COM6", 115200);
cp5 = new ControlP5(this);
PFont pfont = createFont("Arial", 25, true); // use true/false for smooth/no-smooth
ControlFont font = new ControlFont(pfont, 22);
ControlFont font2 = new ControlFont(pfont, 25);
//J1 controls
cp5.addSlider("j1Slider")
.setPosition(80, 222)
.setSize(270, 30)
.setRange(-90, 266) // Slider range, corresponds to Joint 1 or theta1 angle that the robot can move to
.setColorLabel(#3269c2)
.setFont(font)
.setCaptionLabel("")
;
cp5.addButton("j1JogMinus")
.setPosition(80, 275)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG-")
;
cp5.addButton("j1JogPlus")
.setPosition(260, 275)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG+")
;
cp5.addNumberbox("j1JogValue")
.setPosition(190, 275)
.setSize(50, 30)
.setRange(0, 20)
.setFont(font)
.setMultiplier(0.1)
.setValue(1)
.setDirection(Controller.HORIZONTAL) // change the control direction to left/right
.setCaptionLabel("")
;
//J2 controls
cp5.addSlider("j2Slider")
.setPosition(80, 400)
.setSize(270, 30)
.setRange(-150, 150)
.setColorLabel(#3269c2)
.setFont(font)
.setCaptionLabel("")
;
cp5.addButton("j2JogMinus")
.setPosition(80, 450)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG-")
;
cp5.addButton("j2JogPlus")
.setPosition(260, 450)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG+")
;
cp5.addNumberbox("j2JogValue")
.setPosition(190, 450)
.setSize(50, 30)
.setRange(0, 20)
.setFont(font)
.setMultiplier(0.1)
.setValue(1)
.setDirection(Controller.HORIZONTAL) // change the control direction to left/right
.setCaptionLabel("")
;
//J3 controls
cp5.addSlider("j3Slider")
.setPosition(80, 575)
.setSize(270, 30)
.setRange(-162, 162)
.setColorLabel(#3269c2)
.setFont(font)
.setCaptionLabel("")
;
cp5.addButton("j3JogMinus")
.setPosition(80, 625)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG-")
;
cp5.addButton("j3JogPlus")
.setPosition(260, 625)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG+")
;
cp5.addNumberbox("j3JogValue")
.setPosition(190, 625)
.setSize(50, 30)
.setRange(0, 20)
.setFont(font)
.setMultiplier(0.1)
.setValue(1)
.setDirection(Controller.HORIZONTAL) // change the control direction to left/right
.setCaptionLabel("")
;
//Z controls
cp5.addSlider("zSlider")
.setPosition(80, 750)
.setSize(270, 30)
.setRange(-150, 150)
.setColorLabel(#3269c2)
.setFont(font)
.setCaptionLabel("")
;
cp5.addButton("zJogMinus")
.setPosition(80, 800)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG-")
;
cp5.addButton("zJogPlus")
.setPosition(260, 800)
.setSize(90, 40)
.setFont(font)
.setCaptionLabel("JOG+")
;
cp5.addNumberbox("zJogValue")
.setPosition(190, 800)
.setSize(50, 30)
.setRange(0, 20)
.setFont(font)
.setMultiplier(0.1)
.setValue(1)
.setDirection(Controller.HORIZONTAL) // change the control direction to left/right
.setCaptionLabel("")
;
cp5.addTextfield("xTextfield")
.setPosition(460, 340)
.setSize(70, 40)
.setFont(font)
.setColor(255)
.setCaptionLabel("")
;
cp5.addTextfield("yTextfield")
.setPosition(610, 340)
.setSize(70, 40)
.setFont(font)
.setColor(255)
.setCaptionLabel("")
;
cp5.addTextfield("zTextfield")
.setPosition(760, 340)
.setSize(70, 40)
.setFont(font)
.setColor(255)
.setCaptionLabel("")
;
//Z controls
cp5.addSlider("speedSlider")
.setPosition(450, 550)
.setSize(180, 30)
.setRange(500, 4000)
.setColorLabel(#3269c2)
.setFont(font)
.setCaptionLabel("")
;
cp5.addSlider("accelerationSlider")
.setPosition(675, 550)
.setSize(180, 30)
.setRange(500, 4000)
.setColorLabel(#3269c2)
.setFont(font)
.setCaptionLabel("")
;
//Servo Slider
cp5.addSlider("Tilt")
.setPosition(500,200)
.setSize(300,30)
.setRange(-180,180)
.setValue(0)
;
}
void draw() {
background(#F2F2F2); // background black
textSize(35);
fill(33);
text("Stepper Control", 85, 150);
text("Servo Control", 550, 150);
text("Location", 580, 320);
text("Speed Control", 540, 490);
textSize(40);
text("USER INTERFACE", 330, 60);
textSize(22);
text("Stepper #1 (Base-Axis)", 60, 210);
text("Stepper #2 (Arm-Axis)", 60, 385);
text("Stepper #3 (Gripper Axis)", 60, 560);
text("Stepper #4 (Z-Axis)", 60, 735);
textSize(22);
text("Velocity", 500, 535);
text("Acceleration", 700, 535);
//println("PREV: "+accelerationSlider);
fill(speedSlider);
fill(accelerationSlider);
fill(j1Slider);
fill(j2Slider);
fill(j3Slider);
fill(zSlider);
fill(j1JogValue);
fill(j2JogValue);
fill(j3JogValue);
fill(zJogValue);
updateData();
saveStatus=0; // keep savePosition variable 0 or false. See, when button SAVE pressed it makes the value 1, which indicates to store the value in the arduino code
// If slider moved, calculate new position of X,Y and Z with forward kinematics
if (slider1Previous != j1Slider) {
if (activeIK == false) { // Check whether the inverseKinematics mode is active, Executre Forward kinematics only if inverseKinematics mode is off or false
theta1 = round(cp5.getController("j1Slider").getValue()); // get the value from the slider1
theta2 = round(cp5.getController("j2Slider").getValue());
forwardKinematics();
myPort.write(data);
}
}
slider1Previous = j1Slider;
if (slider2Previous != j2Slider) {
if (activeIK == false) { // Check whether the inverseKinematics mode is active, Executre Forward kinematics only if inverseKinematics mode is off or false
theta1 = round(cp5.getController("j1Slider").getValue()); // get the value from the slider1
theta2 = round(cp5.getController("j2Slider").getValue());
forwardKinematics();
myPort.write(data);
}
}
slider2Previous = j2Slider;
if (slider3Previous != j3Slider) {
if (activeIK == false) { // Check whether the inverseKinematics mode is active, Executre Forward kinematics only if inverseKinematics mode is off or false
theta1 = round(cp5.getController("j1Slider").getValue()); // get the value from the slider1
theta2 = round(cp5.getController("j2Slider").getValue());
forwardKinematics();
myPort.write(data);
}
}
slider3Previous = j3Slider;
if (sliderzPrevious != zSlider) {
if (activeIK == false) { // Check whether the inverseKinematics mode is active, Executre Forward kinematics only if inverseKinematics mode is off or false
zP = round(cp5.getController("zSlider").getValue());
updateData();
println(data);
myPort.write(data);
}
}
sliderzPrevious = zSlider;
activeIK = false; // deactivate inverseKinematics so the above if statements can be executed the next interation
fill(33);
textSize(32);
text("X: ", 460, 420);
text(xP, 513, 420);
text("Y: ", 610, 420);
text(yP, 665, 420);
text("Z: ", 760, 420);
text(zP, 815, 420);
textSize(26);
textSize(18);
} //END VOID DRAW
// FORWARD KINEMATICS
void forwardKinematics() {
float theta1F = theta1 * PI / 180; // degrees to radians
float theta2F = theta2 * PI / 180;
xP = round(L1 * cos(theta1F) + L2 * cos(theta1F + theta2F));
yP = round(L1 * sin(theta1F) + L2 * sin(theta1F + theta2F));
}
void controlEvent(ControlEvent theEvent) {
if (theEvent.isController()) {
println(theEvent.getController().getName());
}
}
public void j1JogMinus() {
int a = round(cp5.getController("j1Slider").getValue());
a=a-j1JogValue;
cp5.getController("j1Slider").setValue(a);
}
//J1 control
public void j1JogPlus() {
int a = round(cp5.getController("j1Slider").getValue());
a=a+j1JogValue;
cp5.getController("j1Slider").setValue(a);
}
//J2 control
public void j2JogMinus() {
int a = round(cp5.getController("j2Slider").getValue());
a=a-j2JogValue;
cp5.getController("j2Slider").setValue(a);
}
public void j2JogPlus() {
int a = round(cp5.getController("j2Slider").getValue());
a=a+j2JogValue;
cp5.getController("j2Slider").setValue(a);
}
//J3 control
public void j3JogMinus() {
int a = round(cp5.getController("j3Slider").getValue());
a=a-j3JogValue;
cp5.getController("j3Slider").setValue(a);
}
public void j3JogPlus() {
int a = round(cp5.getController("j3Slider").getValue());
a=a+j3JogValue;
cp5.getController("j3Slider").setValue(a);
}
//J3 control
public void zJogMinus() {
int a = round(cp5.getController("zSlider").getValue());
a=a-zJogValue;
cp5.getController("zSlider").setValue(a);
}
public void zJogPlus() {
int a = round(cp5.getController("zSlider").getValue());
a=a+zJogValue;
;
cp5.getController("zSlider").setValue(a);
}
public void updateData() {
data = str(saveStatus)
+","+str(runStatus)
+","+str(round(cp5.getController("j1Slider").getValue()))
+","+str(round(cp5.getController("j2Slider").getValue()))
+","+str(round(cp5.getController("j3Slider").getValue()))
+","+str(round(cp5.getController("zSlider").getValue()))
+","+str(speedSlider)
+","+str(accelerationSlider);
}
2nd Arduino Code (Servo):
#include <Servo.h>
Servo servo1;
void setup()
{
servo1.attach(A0); //The Tilt servo is attached to pin 9.
Serial.begin(115200); //Set up a serial connection for 57600 bps.
Serial.println("Ready");
}
void loop() {
static int v = 0;
if (Serial.available()){
char ch = Serial.read();
switch (ch) {
case '0'...'9':
v = v * 10 + ch - '0';
break;
case 'a':
servo1.write(v);
Serial.println(v);
v = 0;
break; }
}
}
2nd Processing Code (Servo):
//Processing code:
import processing.serial.*;
import controlP5.*;
ControlP5 cp5;
int tilt = 1;
Serial myPort;
void setup() {
size(500, 250);
myPort = new Serial(this, "COM6", 115200);
cp5 = new ControlP5(this);
cp5.addSlider("pan")
.setPosition(50,70)
.setSize(300,30)
.setRange(0,180)
.setValue(158)
;
cp5.addSlider("tilt")
.setPosition(50,130)
.setSize(300,30)
.setRange(0,180)
.setValue(158)
;
}
void draw() {
myPort.write("a"+tilt);
}