Help with forklift project

i recently was working on a forklift project but have kinda gotten stuck at this part. i am trying to use a similar code from a different machines that was made a quarter or two ago. basically we have 3 stepper motors and they are supposed to move the forklift to a specific location which will be defined once we figure out how many steps we are going to use to make it to said spot. we want to drive the forklift to a rack which has 9 locations colums A, B, and C and then rows 1 2 and 3 (like an excel spreadsheet layout) so there will be A1, A2, A3, etc…

i need to know which of these code parts i dont need so i can make the program smaller but do what it needs to.
im using this code because it already has the stpper motors defined and the arduino pins layed out

basic summary
tell the forklift to go to said spot (example B2)
forklift goes to b2 and load / unloads the material in box
forklift goes backwards with said item loaded or unloaded and then pauses where it started at

i know it is a little confusing im sorry, but if there are any questions ill get back asap, thanks for the help

im going to have to post the code in two parts sorry 1/2

//arduino g-code interpreter

#include <HardwareSerial.h>

//our command string
#define COMMAND_SIZE 128
#include "WProgram.h"
void setup();
void loop();
void init_process_string();
void process_string(char instruction[], int size);
double search_string(char key, char instruction[], int string_size);
bool has_command(char key, char instruction[], int string_size);
void init_steppers();
void dda_move(long micro_delay);
bool can_step(byte min_pin, byte max_pin, long current, long target, byte direction);
void do_step(byte pinA, byte pinB, byte dir);
bool read_switch(byte pin);
long to_steps(float steps_per_unit, float units);
void set_target(float x, float y, float z);
void set_position(float x, float y, float z);
void calculate_deltas();
long calculate_feedrate_delay(float feedrate);
long getMaxSpeed();
void disable_steppers();
char palabra[COMMAND_SIZE];
byte serial_count;
int no_data = 0;


void setup ( )
{
	//startup
	Serial.begin(19200);
	Serial.println ("starting");

	//initilization
	init_process_string ( );
	init_steppers ( );

}

void loop ( )
{
	char c;
	
	//enabling stepper motors
	//if data
	if (Serial.available ( ) > 0 )
		{
		c = Serial.read ( );
		no_data = 0;

		//newlines are ends of command
		
		if (c != '\n' )
		{
			palabra [serial_count] = c;
			serial_count++;
		}
	}
	//no data
	else
	{
		no_data++;
		delayMicroseconds (100);
	}
//if a pause or a command, do it
if (serial_count && (c == '\n' | | no_data > 100 ) )
	{
		//process command
		process_string (palabra, serial_count);
		//clear command
		init_process_string ( ) ;
	}
//if no data, turn off stepper motors
	if (no_data > 1000)
		disable_steppers ( );
}

//define parameters of machine 
#define X_STEPS_PER_INCH 4800
#define X_STEPS_PER_MM 188.97
#define X_MOTOR_STEPS 200

#define Y_STEPS_PER_INCH 4800
#define Y_STEPS_PER_MM 188.97
#define Y_MOTOR_STEPS 200

#define Z_STEPS_PER_INCH 4800
#define Z_STEPS_PER_MM 188.97
#define Z_MOTOR_STEPS 200

//max feedrates
#define FAST_XY_FEEDRATE 100
#define FAST_Z_FEEDRATE 100

//units in curve section
#define CURVE_SECTION_INCHES 0.019685
#define CURVE_SECTION_MM 0.5

#define SENSORS_INVERTING 0

//define i/o pins
#define X_STEP_PIN 8
#define X_DIR_PIN 9 
#define X_MIN_PIN 4
#define X_MAX_PIN 2
#define X_ENABLE_PIN 15

#define Y_STEP_PIN 10
#define Y_DIR_PIN 11
#define Y_MIN_PIN 3
#define Y_MAX_PIN 5
#define Y_ENABLE_PIN 15

#define Z_STEP_PIN 12
#define Z_DIR_PIN 13
#define Z_MIN_PIN 7
#define Z_MAX_PIN 6
#define Z_ENABLE_PIN 15

// point structure
struct Longpoint {
	long x;
	long y;
	long z;
};

struct Floatpoint {
	float x:
	float y;
	float z;
};

FloatPoint current_units;
FloatPoint target_units;
Floatpoint delta_units;

FloatPoint current_steps;
FloatPoint target_steps;
FloatPoint delta_steps;

boolean abs_mode = false;

//default to inches for units
float x_units = X_STEPS_PER_INCHES;
float y_units = Y_STEPS_PER_INCHES;
float z_units = Z_STEPS_PER_INCHES;
float curve_section = CURVE_SECTION_INCHES;

//direction variables
byte x_direction = 1;
byte y_direction = 1;
byte z_direction = 1;

//init the string processing
void init_process_string ( )
{
	for (byte i=0; i<COMMAND_SIZE; i++)
		palabra[i] = 0;
	serial_count = 0;
}

//feedrate variable
float feedrate = 0.0;
long feedrate_micros = 0;

//Read the string and execute instructions
void process_string(char instruction[], int size)
{
	//the character / means delete block... used for comments and stuff.
	if (instruction[0] == '/')
	{
		Serial.println("ok");
		return;
	}

	//init baby!
	FloatPoint fp;
	fp.x = 0.0;
	fp.y = 0.0;
	fp.z = 0.0;

	byte code = 0;;
	

	//did we get a gcode?
	if (
		has_command('G', instruction, size) ||
		has_command('X', instruction, size) ||
		has_command('Y', instruction, size) ||
		has_command('Z', instruction, size)
	)
	{
		//which one?
		code = (int)search_string('G', instruction, size);
		
		// Get co-ordinates if required by the code type given
		switch (code)
		{
			case 0:
			case 1:
			case 2:
			case 3:
				if(abs_mode)
				{
					//we do it like this to save time. makes curves better.
					//eg. if only x and y are specified, we dont have to waste time looking up z.
					if (has_command('X', instruction, size))
						fp.x = search_string('X', instruction, size);
					else
						fp.x = current_units.x;
				
					if (has_command('Y', instruction, size))
						fp.y = search_string('Y', instruction, size);
					else
						fp.y = current_units.y;
				
					if (has_command('Z', instruction, size))
						fp.z = search_string('Z', instruction, size);
					else
						fp.z = current_units.z;
				}
				else
				{
					fp.x = search_string('X', instruction, size) + current_units.x;
					fp.y = search_string('Y', instruction, size) + current_units.y;
					fp.z = search_string('Z', instruction, size) + current_units.z;
				}
			break;
		}

rest of the code sorry for double post
2/2

		//do something!
		switch (code)
		{
			//Rapid Positioning
			//Linear Interpolation
			//these are basically the same thing.
			case 0:
			case 1:
				//set our target.
				set_target(fp.x, fp.y, fp.z);

				//do we have a set speed?
				if (has_command('G', instruction, size))
				{
					//adjust if we have a specific feedrate.
					if (code == 1)
					{
						//how fast do we move?
						feedrate = search_string('F', instruction, size);
						if (feedrate > 0)
							feedrate_micros = calculate_feedrate_delay(feedrate);
						//nope, no feedrate
						else
							feedrate_micros = getMaxSpeed();
					}
					//use our max for normal moves.
					else
						feedrate_micros = getMaxSpeed();
				}
				//nope, just coordinates!
				else
				{
					//do we have a feedrate yet?
					if (feedrate > 0)
						feedrate_micros = calculate_feedrate_delay(feedrate);
					//nope, no feedrate
					else
						feedrate_micros = getMaxSpeed();
				}

				//finally move.
				dda_move(feedrate_micros);
			break;
			
			//Clockwise arc
			case 2:
			//Counterclockwise arc
			case 3:
				FloatPoint cent;

				// Centre coordinates are always relative
				cent.x = search_string('I', instruction, size) + current_units.x;
				cent.y = search_string('J', instruction, size) + current_units.y;
				float angleA, angleB, angle, radius, length, aX, aY, bX, bY;

				aX = (current_units.x - cent.x);
				aY = (current_units.y - cent.y);
				bX = (fp.x - cent.x);
				bY = (fp.y - cent.y);
				
				if (code == 2) { // Clockwise
					angleA = atan2(bY, bX);
					angleB = atan2(aY, aX);
				} else { // Counterclockwise
					angleA = atan2(aY, aX);
					angleB = atan2(bY, bX);
				}

				// Make sure angleB is always greater than angleA
				// and if not add 2PI so that it is (this also takes
				// care of the special case of angleA == angleB,
				// ie we want a complete circle)
				if (angleB <= angleA) angleB += 2 * M_PI;
				angle = angleB - angleA;

				radius = sqrt(aX * aX + aY * aY);
				length = radius * angle;
				int steps, s, step;
				steps = (int) ceil(length / curve_section);

				FloatPoint newPoint;
				for (s = 1; s <= steps; s++) {
					step = (code == 3) ? s : steps - s; // Work backwards for CW
					newPoint.x = cent.x + radius * cos(angleA + angle * ((float) step / steps));
					newPoint.y = cent.y + radius * sin(angleA + angle * ((float) step / steps));
					set_target(newPoint.x, newPoint.y, fp.z);

					// Need to calculate rate for each section of curve
					if (feedrate > 0)
						feedrate_micros = calculate_feedrate_delay(feedrate);
					else
						feedrate_micros = getMaxSpeed();

					// Make step
					dda_move(feedrate_micros);
				}
	
			break;

			//Dwell
			case 4:
				delay((int)search_string('P', instruction, size));
			break;

			//Inches for Units
			case 20:
				x_units = X_STEPS_PER_INCH;
				y_units = Y_STEPS_PER_INCH;
				z_units = Z_STEPS_PER_INCH;
				curve_section = CURVE_SECTION_INCHES;
				
				calculate_deltas();
			break;

			//mm for Units
			case 21:
				x_units = X_STEPS_PER_MM;
				y_units = Y_STEPS_PER_MM;
				z_units = Z_STEPS_PER_MM;
				curve_section = CURVE_SECTION_MM;
				
				calculate_deltas();
			break;

			//go home.
			case 28:
				set_target(0.0, 0.0, 0.0);
				dda_move(getMaxSpeed());
			break;

			//go home via an intermediate point.
			case 30:
				fp.x = search_string('X', instruction, size);
				fp.y = search_string('Y', instruction, size);
				fp.z = search_string('Z', instruction, size);

				//set our target.
				if(abs_mode)
				{
					if (!has_command('X', instruction, size))
						fp.x = current_units.x;
					if (!has_command('Y', instruction, size))
						fp.y = current_units.y;
					if (!has_command('Z', instruction, size))
						fp.z = current_units.z;
						
					set_target(fp.x, fp.y, fp.z);
				}
				else
					set_target(current_units.x + fp.x, current_units.y + fp.y, current_units.z + fp.z);
				
				//go there.
				dda_move(getMaxSpeed());

				//go home.
				set_target(0.0, 0.0, 0.0);
				dda_move(getMaxSpeed());
			break;

			//Absolute Positioning
			case 90:
				abs_mode = true;
			break;

			//Incremental Positioning
			case 91:
				abs_mode = false;
			break;

			//Set as home
			case 92:
				set_position(0.0, 0.0, 0.0);
			break;

/*
			//Inverse Time Feed Mode
			case 93:

			break;  //TODO: add this

			//Feed per Minute Mode
			case 94:

			break;  //TODO: add this
*/

			default:
				Serial.print("huh? G");
				Serial.println(code,DEC);
		}
	}
	
	//find us an m code.
	if (has_command('M', instruction, size))
	{
		code = search_string('M', instruction, size);
		switch (code)
		{
			//TODO: this is a bug because search_string returns 0.  gotta fix that.
			case 0:
				true;
			break;
	
			
		
			
			default:
				Serial.print("Huh? M");
				Serial.println(code);
		}		
	}

ok sorry tbe code was much bigger than i thought, if someone needs it for dl let me know and ill upload it

	//tell our host we're done.
	Serial.println("ok");
//	Serial.println(line, DEC);
}

//look for the number that appears after the char key and return it
double search_string(char key, char instruction[], int string_size)
{
	char temp[10] = "";

	for (byte i=0; i<string_size; i++)
	{
		if (instruction[i] == key)
		{
			i++;      
			int k = 0;
			while (i < string_size && k < 10)
			{
				if (instruction[i] == 0 || instruction[i] == ' ')
					break;

				temp[k] = instruction[i];
				i++;
				k++;
			}
			return strtod(temp, NULL);
		}
	}
	
	return 0;
}

//look for the command if it exists.
bool has_command(char key, char instruction[], int string_size)
{
	for (byte i=0; i<string_size; i++)
	{
		if (instruction[i] == key)
			return true;
	}
	
	return false;
}

//init our variables
long max_delta;
long x_counter;
long y_counter;
long z_counter;
bool x_can_step;
bool y_can_step;
bool z_can_step;
int milli_delay;

void init_steppers()
{
	//turn them off to start.
	disable_steppers();
	
	//init our points.
	current_units.x = 0.0;
	current_units.y = 0.0;
	current_units.z = 0.0;
	target_units.x = 0.0;
	target_units.y = 0.0;
	target_units.z = 0.0;
	
	pinMode(X_STEP_PIN, OUTPUT);
	pinMode(X_DIR_PIN, OUTPUT);
	pinMode(X_ENABLE_PIN, OUTPUT);
	pinMode(X_MIN_PIN, INPUT);
	pinMode(X_MAX_PIN, INPUT);
	
	pinMode(Y_STEP_PIN, OUTPUT);
	pinMode(Y_DIR_PIN, OUTPUT);
	pinMode(Y_ENABLE_PIN, OUTPUT);
	pinMode(Y_MIN_PIN, INPUT);
	pinMode(Y_MAX_PIN, INPUT);
	
	pinMode(Z_STEP_PIN, OUTPUT);
	pinMode(Z_DIR_PIN, OUTPUT);
	pinMode(Z_ENABLE_PIN, OUTPUT);
	pinMode(Z_MIN_PIN, INPUT);
	pinMode(Z_MAX_PIN, INPUT);
	
	//figure our stuff.
	calculate_deltas();
}

void dda_move(long micro_delay)
{
	//enable our steppers
	digitalWrite(X_ENABLE_PIN, HIGH);
	digitalWrite(Y_ENABLE_PIN, HIGH);
	digitalWrite(Z_ENABLE_PIN, HIGH);
	
	//figure out our deltas
	max_delta = max(delta_steps.x, delta_steps.y);
	max_delta = max(delta_steps.z, max_delta);

	//init stuff.
	long x_counter = -max_delta/2;
	long y_counter = -max_delta/2;
	long z_counter = -max_delta/2;
	
	//our step flags
	bool x_can_step = 0;
	bool y_can_step = 0;
	bool z_can_step = 0;
	
	if (micro_delay >= 16383)
		milli_delay = micro_delay / 1000;
	else
		milli_delay = 0;

	//do our DDA line!
	do
	{
		x_can_step = can_step(X_MIN_PIN, X_MAX_PIN, current_steps.x, target_steps.x, x_direction);
		y_can_step = can_step(Y_MIN_PIN, Y_MAX_PIN, current_steps.y, target_steps.y, y_direction);
		z_can_step = can_step(Z_MIN_PIN, Z_MAX_PIN, current_steps.z, target_steps.z, z_direction);

		if (x_can_step)
		{
			x_counter += delta_steps.x;
			
			if (x_counter > 0)
			{
				do_step(X_STEP_PIN, X_DIR_PIN, x_direction);
				x_counter -= max_delta;
				
				if (x_direction)
					current_steps.x++;
				else
					current_steps.x--;
			}
		}

		if (y_can_step)
		{
			y_counter += delta_steps.y;
			
			if (y_counter > 0)
			{
				do_step(Y_STEP_PIN, Y_DIR_PIN, y_direction);
				y_counter -= max_delta;

				if (y_direction)
					current_steps.y++;
				else
					current_steps.y--;
			}
		}
		
		if (z_can_step)
		{
			z_counter += delta_steps.z;
			
			if (z_counter > 0)
			{
				do_step(Z_STEP_PIN, Z_DIR_PIN, z_direction);
				z_counter -= max_delta;
				
				if (z_direction)
					current_steps.z++;
				else
					current_steps.z--;
			}
		}
		
		
				
		//wait for next step.
		if (milli_delay > 0)
			delay(milli_delay);			
		else
			delayMicroseconds(micro_delay);
	}
	while (x_can_step || y_can_step || z_can_step);
	
	//set our points to be the same
	current_units.x = target_units.x;
	current_units.y = target_units.y;
	current_units.z = target_units.z;
	calculate_deltas();
}

bool can_step(byte min_pin, byte max_pin, long current, long target, byte direction)
{
	//stop us if we're on target
	if (target == current)
		return false;
	//stop us if we're at home and still going 
	else if (read_switch(min_pin) && !direction)
		return false;
	//stop us if we're at max and still going
	else if (read_switch(max_pin) && direction)
		return false;

	//default to being able to step
	return true;
}

void do_step(byte pinA, byte pinB, byte dir)
{
        switch (dir << 2 | digitalRead(pinA) << 1 | digitalRead(pinB)) {
            case 0: /* 0 00 -> 10 */
            case 5: /* 1 01 -> 11 */
                digitalWrite(pinA, HIGH);
                break;
            case 1: /* 0 01 -> 00 */
            case 7: /* 1 11 -> 10 */
                digitalWrite(pinB, LOW);
                break;
            case 2: /* 0 10 -> 11 */
            case 4: /* 1 00 -> 01 */   
                digitalWrite(pinB, HIGH);
                break;
            case 3: /* 0 11 -> 01 */
            case 6: /* 1 10 -> 00 */
                digitalWrite(pinA, LOW);
                break;
        }
	delayMicroseconds(5);
}


bool read_switch(byte pin)
{
	//dual read as crude debounce
	
	if ( SENSORS_INVERTING )
		return !digitalRead(pin) && !digitalRead(pin);
	else
		return digitalRead(pin) && digitalRead(pin);
}

long to_steps(float steps_per_unit, float units)
{
	return steps_per_unit * units;
}

void set_target(float x, float y, float z)
{
	target_units.x = x;
	target_units.y = y;
	target_units.z = z;
	
	calculate_deltas();
}

void set_position(float x, float y, float z)
{
	current_units.x = x;
	current_units.y = y;
	current_units.z = z;
	
	calculate_deltas();
}

void calculate_deltas()
{
	//figure our deltas.
	delta_units.x = abs(target_units.x - current_units.x);
	delta_units.y = abs(target_units.y - current_units.y);
	delta_units.z = abs(target_units.z - current_units.z);
				
	//set our steps current, target, and delta
	current_steps.x = to_steps(x_units, current_units.x);
	current_steps.y = to_steps(y_units, current_units.y);
	current_steps.z = to_steps(z_units, current_units.z);

	target_steps.x = to_steps(x_units, target_units.x);
	target_steps.y = to_steps(y_units, target_units.y);
	target_steps.z = to_steps(z_units, target_units.z);

	delta_steps.x = abs(target_steps.x - current_steps.x);
	delta_steps.y = abs(target_steps.y - current_steps.y);
	delta_steps.z = abs(target_steps.z - current_steps.z);
	
	//what is our direction
	x_direction = (target_units.x >= current_units.x);
	y_direction = (target_units.y >= current_units.y);
	z_direction = (target_units.z >= current_units.z);

	//set our direction pins as well
	digitalWrite(X_DIR_PIN, x_direction);
	digitalWrite(Y_DIR_PIN, y_direction);
	digitalWrite(Z_DIR_PIN, z_direction);
}


long calculate_feedrate_delay(float feedrate)
{
	//how long is our line length?
	float distance = sqrt(delta_units.x*delta_units.x + delta_units.y*delta_units.y + delta_units.z*delta_units.z);
	long master_steps = 0;
	
	//find the dominant axis.
	if (delta_steps.x > delta_steps.y)
	{
		if (delta_steps.z > delta_steps.x)
			master_steps = delta_steps.z;
		else
			master_steps = delta_steps.x;
	}
	else
	{
		if (delta_steps.z > delta_steps.y)
			master_steps = delta_steps.z;
		else
			master_steps = delta_steps.y;
	}

	return ((distance * 600000000.0) / feedrate) / master_steps;	
}

long getMaxSpeed()
{
	if (delta_steps.z > 0)
		return calculate_feedrate_delay(FAST_Z_FEEDRATE);
	else
		return calculate_feedrate_delay(FAST_XY_FEEDRATE);
}

void disable_steppers()
{
	//enable our steppers
	digitalWrite(X_ENABLE_PIN, LOW);
	digitalWrite(Y_ENABLE_PIN, LOW);
	digitalWrite(Z_ENABLE_PIN, LOW);
}

int main(void)
{
	init();

	setup();
    
	for (;;)
		loop();
        
	return 0;
}

Do you want to use Gcode which is what it interprets on the Serial input to move steppers? It presumes that we have X, Y and Z axis, each driven by one motor. If your Forklift mechanical arragements is differnet from that, then your reuse is limited to init_steppers() and dda_move() and stuff it calls.

I have only skimmed the code - it has a main() and defines function prototypes - it wont compile in the normal IDE.

HHmmm.... well yes, there are two ways to devlop code. Write it your self, building it up from small bits; and taking working code from else where (which is usually what happens when one uses a library). Or read others code, and be inspired to write your own. I usually use the 3rd.

Msquare:
there are two ways to devlop code… I usually use the 3rd.

:smiley:

Msquare:
Do you want to use Gcode which is what it interprets on the Serial input to move steppers? It presumes that we have X, Y and Z axis, each driven by one motor. If your Forklift mechanical arragements is differnet from that, then your reuse is limited to init_steppers() and dda_move() and stuff it calls.

I have only skimmed the code - it has a main() and defines function prototypes - it wont compile in the normal IDE.

HHmmm.... well yes, there are two ways to devlop code. Write it your self, building it up from small bits; and taking working code from else where (which is usually what happens when one uses a library). Or read others code, and be inspired to write your own. I usually use the 3rd.

what would you recommend for the compiling, i was having issues with that as well

Gcode
x - controlling forward and backwards
y - controlling up and down
z - controlling the forks on the forklift

john92:
what would you recommend for the compiling, i was having issues with that as well

Remove the lines that define a prototype (The trailing ";" is what makes it a prototype.) like:

void setup();

Remove the main() function. The #include lines are redundant, remove them, too.

When using other code it presumes that either the code is documented (meaning somewhere it is explained what each function does - ie how to call them, not necessarily how they work internally) OR you can read and understand code and thus substitute for the missing documentation or you can pick out the sections you need and/or modify them. How well qualified do you feel to that task (it is always OK to ask on the forum for "tricky details")

Msquare:

john92:
what would you recommend for the compiling, i was having issues with that as well

Remove the lines that define a prototype (The trailing “;” is what makes it a prototype.) like:

void setup();

Remove the main() function. The #include lines are redundant, remove them, too.

When using other code it presumes that either the code is documented (meaning somewhere it is explained what each function does - ie how to call them, not necessarily how they work internally) OR you can read and understand code and thus substitute for the missing documentation or you can pick out the sections you need and/or modify them. How well qualified do you feel to that task (it is always OK to ask on the forum for “tricky details”)

ok with that done it should look like this i believe
pretty much all im looking to do as of now it get the program loaded to the arduino letting me control how many steps to make each stepper motor work correctly, getting them to go to the boxes is something that will just take some tweaking, i was just confused which codes are needed to do this without leaving something vital or important missing. The code im basing it off of was a sign carving arduino. you would load what you want it to make the stencil of and then it would move the drill using XYZ to cut said object out

//arduino g-code interpreter

#include <HardwareSerial.h>

//our command string
#define COMMAND_SIZE 128
#include "WProgram.h"

void setup ( )
{
	//startup
	Serial.begin(19200);
	Serial.println ("starting");

	//initilization
	init_process_string ( );
	init_steppers ( );

}

void loop ( )
{
	char c;
	
	//enabling stepper motors
	//if data
	if (Serial.available ( ) > 0 )
		{
		c = Serial.read ( );
		no_data = 0;

		//newlines are ends of command
		
		if (c != '\n' )
		{
			palabra [serial_count] = c;
			serial_count++;
		}
	}
	//no data
	else
	{
		no_data++;
		delayMicroseconds (100);
	}
//if a pause or a command, do it
if (serial_count && (c == '\n' | | no_data > 100 ) )
	{
		//process command
		process_string (palabra, serial_count);
		//clear command
		init_process_string ( ) ;
	}
//if no data, turn off stepper motors
	if (no_data > 1000)
		disable_steppers ( );
}

//define parameters of machine 
#define X_STEPS_PER_INCH 4800
#define X_STEPS_PER_MM 188.97
#define X_MOTOR_STEPS 200

#define Y_STEPS_PER_INCH 4800
#define Y_STEPS_PER_MM 188.97
#define Y_MOTOR_STEPS 200

#define Z_STEPS_PER_INCH 4800
#define Z_STEPS_PER_MM 188.97
#define Z_MOTOR_STEPS 200

//max feedrates
#define FAST_XY_FEEDRATE 100
#define FAST_Z_FEEDRATE 100

//units in curve section
#define CURVE_SECTION_INCHES 0.019685
#define CURVE_SECTION_MM 0.5

#define SENSORS_INVERTING 0

//define i/o pins
#define X_STEP_PIN 8
#define X_DIR_PIN 9 
#define X_MIN_PIN 4
#define X_MAX_PIN 2
#define X_ENABLE_PIN 15

#define Y_STEP_PIN 10
#define Y_DIR_PIN 11
#define Y_MIN_PIN 3
#define Y_MAX_PIN 5
#define Y_ENABLE_PIN 15

#define Z_STEP_PIN 12
#define Z_DIR_PIN 13
#define Z_MIN_PIN 7
#define Z_MAX_PIN 6
#define Z_ENABLE_PIN 15

// point structure
struct Longpoint {
	long x;
	long y;
	long z;
};

struct Floatpoint {
	float x:
	float y;
	float z;
};

FloatPoint current_units;
FloatPoint target_units;
Floatpoint delta_units;

FloatPoint current_steps;
FloatPoint target_steps;
FloatPoint delta_steps;

boolean abs_mode = false;

//default to inches for units
float x_units = X_STEPS_PER_INCHES;
float y_units = Y_STEPS_PER_INCHES;
float z_units = Z_STEPS_PER_INCHES;
float curve_section = CURVE_SECTION_INCHES;

//direction variables
byte x_direction = 1;
byte y_direction = 1;
byte z_direction = 1;

//init the string processing
void init_process_string ( )
{
	for (byte i=0; i<COMMAND_SIZE; i++)
		palabra[i] = 0;
	serial_count = 0;
}

//feedrate variable
float feedrate = 0.0;
long feedrate_micros = 0;

//Read the string and execute instructions
void process_string(char instruction[], int size)
{
	//the character / means delete block... used for comments and stuff.
	if (instruction[0] == '/')
	{
		Serial.println("ok");
		return;
	}

	//init baby!
	FloatPoint fp;
	fp.x = 0.0;
	fp.y = 0.0;
	fp.z = 0.0;

	byte code = 0;;
	

	//did we get a gcode?
	if (
		has_command('G', instruction, size) ||
		has_command('X', instruction, size) ||
		has_command('Y', instruction, size) ||
		has_command('Z', instruction, size)
	)
	{
		//which one?
		code = (int)search_string('G', instruction, size);
		
		// Get co-ordinates if required by the code type given
		switch (code)
		{
			case 0:
			case 1:
			case 2:
			case 3:
				if(abs_mode)
				{
					//we do it like this to save time. makes curves better.
					//eg. if only x and y are specified, we dont have to waste time looking up z.
					if (has_command('X', instruction, size))
						fp.x = search_string('X', instruction, size);
					else
						fp.x = current_units.x;
				
					if (has_command('Y', instruction, size))
						fp.y = search_string('Y', instruction, size);
					else
						fp.y = current_units.y;
				
					if (has_command('Z', instruction, size))
						fp.z = search_string('Z', instruction, size);
					else
						fp.z = current_units.z;
				}
				else
				{
					fp.x = search_string('X', instruction, size) + current_units.x;
					fp.y = search_string('Y', instruction, size) + current_units.y;
					fp.z = search_string('Z', instruction, size) + current_units.z;
				}
			break;
		}

Have you tried the program you've included? What happens?

i think i may of figured out what i need to do, but feel free to add your input to the idea. i am going to buy three easy drivers and then hook them up to arudino uno

i found a code to control three stepper motors that would be for a cnc machine

edit - i need to find a way to add a switch or something to control when i want each motor on however

#define DIR1_PIN 4
#define STEP1_PIN 5
#define DIR2_PIN 6
#define STEP2_PIN 7
#define DIR3_PIN 8
#define STEP3_PIN 9
#define DELAY 150


void setup() {
Serial.begin(9600);
pinMode(DIR1_PIN,OUTPUT);
pinMode(STEP1_PIN,OUTPUT);
pinMode(DIR2_PIN,OUTPUT);
pinMode(STEP2_PIN,OUTPUT);
pinMode(DIR3_PIN,OUTPUT);
pinMode(STEP3_PIN,OUTPUT);
}


void loop() {
int i;

digitalWrite(DIR1_PIN, LOW); // Set the direction.
digitalWrite(DIR2_PIN, LOW); // Set the direction.
digitalWrite(DIR3_PIN, LOW); // Set the direction.
delay(DELAY);
Serial.println(">>");

for (i = 0; i<6800; i++) // Iterate for 4000 microsteps.
{
digitalWrite(STEP1_PIN, LOW); // This LOW to HIGH change is what creates the
digitalWrite(STEP1_PIN, HIGH); // "Rising Edge" so the easydriver knows to when to step.
if((i%2)==0) {
digitalWrite(STEP2_PIN, LOW); // This LOW to HIGH change is what creates the
digitalWrite(STEP2_PIN, HIGH); // "Rising Edge" so the easydriver knows to when to step.
}
if((i%4)==0) {
digitalWrite(STEP3_PIN, LOW); // This LOW to HIGH change is what creates the
digitalWrite(STEP3_PIN, HIGH); // "Rising Edge" so the easydriver knows to when to step.
}
delayMicroseconds(DELAY); // This delay time is close to top speed for this
} // particular motor. Any faster the motor stalls.

digitalWrite(DIR1_PIN, HIGH); // Change direction.
digitalWrite(DIR2_PIN, HIGH); // Change direction.
digitalWrite(DIR3_PIN, HIGH); // Change direction.
delay(DELAY);
Serial.println("<<");

for (i = 0; i<6800; i++) // Iterate for 4000 microsteps
{
digitalWrite(STEP1_PIN, LOW); // This LOW to HIGH change is what creates the
digitalWrite(STEP1_PIN, HIGH); // "Rising Edge" so the easydriver knows to when to step.
if((i%2)==0) {
digitalWrite(STEP2_PIN, LOW); // This LOW to HIGH change is what creates the
digitalWrite(STEP2_PIN, HIGH); // "Rising Edge" so the easydriver knows to when to step.
}
if((i%4)==0) {
digitalWrite(STEP3_PIN, LOW); // This LOW to HIGH change is what creates the
digitalWrite(STEP3_PIN, HIGH); // "Rising Edge" so the easydriver knows to when to step.
}
delayMicroseconds(DELAY); // This delay time is close to top speed for this
} // particular motor. Any faster the motor stalls.
}

Well, what do you think this program does?

I ask, because if you think you can “insert” some code to control the start stop the motors, you should be able to see what it does, in order to determine where to insert your modification.

I think the program is delightfully simple, so you can use it as inspiration to write your own. Rather, it is easier to write your own than try and edit this, although you will probably reuse half the code, but individual lines, not whole routines.

I did a simple program to controll two stepprs a while back. This is not a well documented nor well written program becuse I only used it for short test. When running and connect up to the Serial monitor, I can enter commands like 500R100L-222R resulting in one stepper moving 500 steps and then the other moving 100 steps and then the first stepper going backwards 222 steps.

Attached as 3 files (you can do that under “additional options” when you write your next post with very long code) as more inspiration for your own program. Replace the “Around.onestep” (and similar) with the code from your last example that does a step. Ignore the servo stuff. the “nnnC” library does the command parsing, in the main program it is the code that examines the “X” and “N” variables that interprets the command.

EggBotTest.ino (1.43 KB)

nnnC.cpp (4.35 KB)

nnnC.h (2.46 KB)

ok after a little work i think i put together a file that will do what i need it to do for now. i created this file to move one motor foward then motor 2 and then motor 3. once that is dont it will move them backwards starting with motor 3, then 2, then 1. Take a look at my code, it compiled with no errors lemme know if you see any issues or suggestions.

Forkedd2_0.ino (2.33 KB)

Seems simple and straight forward enough. Now we just have to wait for some actual circuitry and actual steppers and actual movement, right?

I have loads of "dotting the i's and crossing the t's" suggestions, but they won't make your program work any better/faster so I'll restrain myself :wink: this time. Lets see it run first.

ok after a lot of research and tinkering i kinda found an approach to do what i am trying to do. i forgot we already have someone making the h bridge for the project so easy drivers are out of the question, so revamp was imminent. However, i think it gave me a better opportunity and understanding. if this works the way i need it to it might be what i need to get the job done

the if else statement that executes for each command is the same as of now until we test the motors and see where each one needs to go exactly, this is just a test until i can make it back to the group tomorrow

lemme know what you think

#include <Stepper.h>
#define motorSteps 200     // change this depending on the number of steps per revolution of your motor

boolean stringComplete = false;
String inputStr = "";

int XStep = 8;
int XDir = 9;
int XMin = 4;
int XMax = 2;

int YStep = 10;
int YDir = 11;
int YMin = 3;
int YMax = 5;

int ZStep = 12;
int ZDir = 13;
int ZMin = 7;
int ZMax = 6;

int En = 15;
int delayTime = 500;
int ledmode = 1;

Stepper X(motorSteps, 8, 9, 4, 2);
Stepper Y(motorSteps, 10, 11, 3, 5);
Stepper Z(motorSteps, 12, 13, 7, 6);

void setup()
{
  pinMode(XStep, OUTPUT);
  pinMode(XDir, OUTPUT);
  pinMode(XMin, OUTPUT);
  pinMode(XMax, OUTPUT);
  pinMode(YStep, OUTPUT);
  pinMode(YDir, OUTPUT);
  pinMode(YMin, OUTPUT);
  pinMode(YMax, OUTPUT);
  pinMode(ZStep, OUTPUT);
  pinMode(ZDir, OUTPUT);
  pinMode(ZMin, OUTPUT);
  pinMode(ZMax, OUTPUT);

  X.setSpeed(60); // motor speed
  Y.setSpeed(60);
  Z.setSpeed(60);

  Serial.begin(9600);
  inputStr.reserve(200); //reserve some memory for input string
  print_menu();
}

void print_menu() {
  Serial.println();
  Serial.println("Enter number or type command:");
  Serial.println("1. A1");
  Serial.println("2. A2");
  Serial.println("3. A3");  
  Serial.println("4. B1");
  Serial.println("5. B2");
  Serial.println("6. B3");  
  Serial.println("7. C1");
  Serial.println("8. C2");
  Serial.println("9. C3");    
  Serial.print("> ");   
}

void get_input()
{
  char inChar = Serial.read();
  if(inChar == 8 || inChar == 127) { //backspace or delete
    int len = inputStr.length();
    inputStr = inputStr.substring(0, len -1);
  } 
  else {
    inputStr += (char)inChar;
  }
  if(inChar == '\n') {
    inputStr.trim(); //clean up the string
    stringComplete = true;
  }
}

void loop()
{
  if(ledmode == 1) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300); 

  } 
  else if (ledmode == 2) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  } 
  else if (ledmode == 3) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  }  
  else if (ledmode == 4) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  }  
  else if (ledmode == 5) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  }  
  else if (ledmode == 6) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  }  
  else if (ledmode == 7) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  }  
  else if (ledmode == 8) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  }  
  else if (ledmode == 9) {
    X.step(300);
    delay(300); 
    Y.step(300);
    delay(300); 
    Z.step(300);
    delay(300); 
    Z.step(-300);
    delay(300); 
    Y.step(-300);
    delay(300); 
    X.step(-300);
    delay(300);  
  } 
  //When done print text
  if(stringComplete) {
    if(inputStr == "1" || inputStr == "A1") {
      Serial.println("Fethcing A1");
      ledmode = 1;
    } 
    else if (inputStr == "2" || inputStr == "A2") {
      Serial.println("Fetching A2");   
      ledmode = 2;
    } 
    else if (inputStr == "3" || inputStr == "A3") {
      Serial.println("Fetching A3");
      ledmode = 3;
    } 
    else if (inputStr == "4" || inputStr == "B1") {
      Serial.println("Fecthing B1");
      ledmode = 4;
    } 
    else if (inputStr == "5" || inputStr == "B2") {
      Serial.println("Fetching B2");
      ledmode = 5;
    } 
    else if (inputStr == "6" || inputStr == "B3") {
      Serial.println("Fetching B3");
      ledmode = 6;
    } 
    else if (inputStr == "7" || inputStr == "C1") {
      Serial.println("Fetching C1");
      ledmode = 7;
    } 
    else if (inputStr == "8" || inputStr == "C2") {
      Serial.println("Fetching C2");
      ledmode = 8;
    } 
    else if (inputStr == "9" || inputStr == "C3") {
      Serial.println("Fetching C3");
      ledmode = 9;
    } 
    else {
      Serial.println("Command \"" + inputStr + "\" not valid!"); 
    }
    inputStr = "";
    stringComplete = false;
    print_menu();
  }
}

void serialEvent() {
  while(Serial.available()) { // Make sure there is a key press
    get_input();
  }
}

Forkedd3_1.ino (5.12 KB)