let's improve our machine!
/*
* V0 : Benoit Sobrie
* - Convert X,Y coordinate to A,B belt length.
* - Can draw lines with provided (absolute) coordinates.
* - Write the letter F and A.
* - Use RAMPS as controler.
*/
#define A_STEP_PIN 54 // X
#define A_DIR_PIN 55
#define A_ENABLE_PIN 38
#define B_STEP_PIN 60 // Y
#define B_DIR_PIN 61
#define B_ENABLE_PIN 56
#define STEP_DELAY 500 // Motor speed
#define STEP_ENDDELAY 500 // Motor speed
//Distance between stepper motor shafts
#define W 728
#define DIR_REVERSE_A
//#define DIR_REVERSE_B
#define STEPS_PER_mm_A 80 //80 with 1/16 microstep, GT2 belt and 20 tooth
#define STEPS_PER_mm_B 80 //80 with 1/16 microstep, GT2 belt and 20 tooth
#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINTLN(x) Serial.println (x);
#define DEBUG_PRINT(x) Serial.print (x);
#else
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINT(x)
#endif
#ifdef DEBUGSTEPPER
#define DEBUGSTEPPER_PRINTLN(x) Serial.println (x);
#define DEBUGSTEPPER_PRINT(x) Serial.print (x);
#else
#define DEBUGSTEPPER_PRINTLN(x)
#define DEBUGSTEPPER_PRINT(x)
#endif
bool start = true;
float xpen0=100.f;
float ypen0=100.f;
typedef struct point
{
float x;
float y;
} point;
void setup() {
Serial.begin(115200);
SetupStepper();
}
void SetupStepper() {
DEBUG_PRINT("# Stepper A : (E:")
DEBUG_PRINT(A_ENABLE_PIN)
DEBUG_PRINT(",S:")
DEBUG_PRINT(A_STEP_PIN)
DEBUG_PRINT(",D:")
DEBUG_PRINT(A_DIR_PIN)
DEBUG_PRINTLN(")")
pinMode(A_ENABLE_PIN,OUTPUT); // Enable
pinMode(A_STEP_PIN,OUTPUT); // Step
pinMode(A_DIR_PIN,OUTPUT); // Dir
digitalWrite(A_ENABLE_PIN,HIGH); // Set !Enable high
DEBUG_PRINT("# Stepper B : (E:")
DEBUG_PRINT(B_ENABLE_PIN)
DEBUG_PRINT(",S:")
DEBUG_PRINT(B_STEP_PIN)
DEBUG_PRINT(",D:")
DEBUG_PRINT(B_DIR_PIN)
DEBUG_PRINTLN(")")
pinMode(B_ENABLE_PIN,OUTPUT); // Enable
pinMode(B_STEP_PIN,OUTPUT); // Step
pinMode(B_DIR_PIN,OUTPUT); // Dir
digitalWrite(B_ENABLE_PIN,HIGH); // Set !Enable high
}
void loop() {
DEBUG_PRINTLN("# Ready waiting Serial input")
if(Serial.read() != -1){
letterF(xpen0,ypen0);
traceligne(xpen0,ypen0+100,xpen0+100,ypen0+100);
letterA(xpen0+100,ypen0+100);
traceligne(xpen0+150,ypen0+100, xpen0,ypen0);
}
start = false;
}
void letterF(float x0,float y0) {
traceligne(x0,y0,x0+50,y0);
traceligne(x0+50,y0,x0,y0);
traceligne(x0,y0,x0,y0+50);
traceligne(x0,y0+50,x0+50,y0+50);
traceligne(x0+50,y0+50,x0,y0+50);
traceligne(x0,y0+50,x0,y0+100);
}
void letterA(float x0,float y0) {
traceligne(x0,y0,x0+12.5,y0-50);
traceligne(x0+12.5,y0-50,x0+37.5,y0-50);
traceligne(x0+37.5,y0-50,x0+25,y0-100);
traceligne(x0+25,y0-100,x0+12.5,y0-50);
traceligne(x0+12.5,y0-50,x0+37.5,y0-50);
traceligne(x0+37.5,y0-50,x0+50,y0);
}
void traceligne(float x0, float y0, float x1, float y1) {
point origin;
point destination;
point originAB;
point destinationAB;
DEBUG_PRINT("# TraceLigne : (")
DEBUG_PRINT(x0)
DEBUG_PRINT(",")
DEBUG_PRINT(y0)
DEBUG_PRINT(")(");
DEBUG_PRINT(x1)
DEBUG_PRINT(",")
DEBUG_PRINT(y1)
DEBUG_PRINTLN(")");
origin.x = x0;
origin.y = y0;
destination.x = x1;
destination.y = y1;
originAB = convert2ABcoord(origin);
destinationAB = convert2ABcoord(destination);
moveAB(originAB,destinationAB);
}
void moveAB(point p0, point p1) {
DEBUG_PRINT("# Move AB : (")
DEBUG_PRINT(p0.x)
DEBUG_PRINT(",")
DEBUG_PRINT(p0.y)
DEBUG_PRINT(")(");
DEBUG_PRINT(p1.x)
DEBUG_PRINT(",")
DEBUG_PRINT(p1.y)
DEBUG_PRINTLN(")");
float dA = p1.x - p0.x;
float dB = p1.y - p0.y;
bool Adir = (dA >= 0) ? true : false;
bool Bdir = (dB >= 0) ? true : false;
unsigned long Astep = abs(dA) * STEPS_PER_mm_A;
unsigned long Bstep = abs(dB) * STEPS_PER_mm_B;
DEBUG_PRINT("# AB Steps : ")
DEBUG_PRINT(Astep)
DEBUG_PRINT(",")
DEBUG_PRINTLN(Bstep)
if(Astep == 0) StepB(Bdir, Bstep);
else {
if(Bstep == 0) StepA(Adir, Astep);
else {
float k = (float) Bstep / (float)Astep;
unsigned long AstepStatus = 0;
unsigned long BstepStatus = 0;
float cerror = 0;
float error = 0;
unsigned long nstep = 0;
if(k>=1) {
nstep = k;
error = k - nstep;
while(AstepStatus < Astep) {
StepA(Adir, 1);
cerror += error;
if(cerror >= 1) {
int missingsteps = cerror;
cerror -= missingsteps;
StepB(Bdir, nstep + missingsteps);
}
else {
StepB(Bdir, nstep);
}
AstepStatus ++;
}
}
else {
k = 1 / k;
nstep = k;
error = k - nstep;
while(BstepStatus < Bstep) {
StepB(Bdir, 1);
cerror += error;
if(cerror >= 1) {
int missingsteps = cerror;
cerror -= missingsteps;
StepA(Adir, nstep + missingsteps);
}
else {
StepA(Adir, nstep);
}
BstepStatus ++;
}
}
}
}
}
point convert2ABcoord(point coord) {
point res;
float px0 = pow(coord.x,2);
float py0 = pow(coord.y,2);
float pwx0 = pow((W-coord.x),2);
res.x = sqrt(px0 + py0);
res.y = sqrt(pwx0 + py0);
return res;
}
void StepA(bool dir, unsigned long nStep) {
#ifdef DIR_REVERSE_A
DEBUGSTEPPER_PRINTLN("# Stepper A : Reverse direction")
Step(!dir, A_DIR_PIN, A_ENABLE_PIN, A_STEP_PIN, nStep);
#else
DEBUGSTEPPER_PRINTLN("# Stepper A : Normal direction")
Step(dir, A_DIR_PIN, A_ENABLE_PIN, A_STEP_PIN, nStep);
#endif
}
void StepB(bool dir, unsigned long nStep) {
#ifdef DIR_REVERSE_B
DEBUGSTEPPER_PRINTLN("# Stepper B : Reverse direction")
Step(!dir, B_DIR_PIN, B_ENABLE_PIN, B_STEP_PIN, nStep);
#else
DEBUGSTEPPER_PRINTLN("# Stepper B : Normal direction")
Step(dir, B_DIR_PIN, B_ENABLE_PIN, B_STEP_PIN, nStep);
#endif
}
void Step(bool dir, int dirPin, int enablePin, int stepPin, unsigned long nStep) {
DEBUGSTEPPER_PRINT("# Stepper : (")
DEBUGSTEPPER_PRINT(dir)
DEBUGSTEPPER_PRINT(",")
DEBUGSTEPPER_PRINT(nStep)
DEBUGSTEPPER_PRINTLN(")")
digitalWrite(enablePin,LOW);
if(dir) {
digitalWrite(dirPin, LOW);
}
else {
digitalWrite(dirPin, HIGH);
}
for(unsigned long i=0; i < nStep; i++) {
digitalWrite(stepPin,HIGH); // Output high
delayMicroseconds(STEP_DELAY); //delay(STEP_DELAY); // Wait
digitalWrite(stepPin,LOW); // Output low
delayMicroseconds(STEP_ENDDELAY); //delay(STEP_ENDDELAY); // Wait
}
digitalWrite(enablePin,HIGH);
Summary :
This part was really fun, except the code who was really tricky. More informations about the next part can be found in our BXL group page