From: Mjolnir Date: Wed, 19 Aug 2015 09:05:27 +0000 (+0200) Subject: mouse arduino code X-Git-Url: https://git.thomaspietrzak.com/?a=commitdiff_plain;h=3e2ca5335da917baf92c69eea68f66048583b2f2;p=livingdesktop.git mouse arduino code --- diff --git a/GCodeParser/GCodeParser.ino b/GCodeParser/GCodeParser.ino new file mode 100644 index 0000000..c658da7 --- /dev/null +++ b/GCodeParser/GCodeParser.ino @@ -0,0 +1,162 @@ +/* + Pin numbers adapted +*/ + +#include +// define the parameters of our machine. +float X_STEPS_PER_INCH = 48; +float X_STEPS_PER_MM = 40; +int X_MOTOR_STEPS = 100; + +float Y_STEPS_PER_INCH = 48; +float Y_STEPS_PER_MM = 40; +int Y_MOTOR_STEPS = 100; + +float Z_STEPS_PER_INCH = 48; +float Z_STEPS_PER_MM = 40; +int Z_MOTOR_STEPS = 100; + +//our maximum feedrates +long FAST_XY_FEEDRATE = 2000; +long FAST_Z_FEEDRATE = 2000; + +// Units in curve section +#define CURVE_SECTION_INCHES 0.019685 +#define CURVE_SECTION_MM 0.5 + +// Set to one if sensor outputs inverting (ie: 1 means open, 0 means closed) +// RepRap opto endstops are *not* inverting. +int SENSORS_INVERTING = 1; + +// How many temperature samples to take. each sample takes about 100 usecs. + + +/**************************************************************************************** +* digital i/o pin assignment +* +* this uses the undocumented feature of Arduino - pins 14-19 correspond to analog 0-5 +****************************************************************************************/ +/* +int X_STEP_PIN = 8; +int X_DIR_PIN = 11; +int X_ENABLE_PIN = 4; +int X_MIN_PIN = A4; +int X_MAX_PIN = A5; + +int Y_STEP_PIN = 12; +int Y_DIR_PIN = 13; +int Y_ENABLE_PIN = 4; +int Y_MIN_PIN = A1; +int Y_MAX_PIN = A0; + +int Z_STEP_PIN = A3; +int Z_DIR_PIN = 9; +int Z_ENABLE_PIN = 4; +int Z_MIN_PIN = A1; +int Z_MAX_PIN = A0; +int Z_ENABLE_SERVO = 1;*/ + +int X_STEP_PIN = 10; +int X_DIR_PIN = 11; +int X_ENABLE_PIN = -1; +int X_MIN_PIN = 17; +int X_MAX_PIN = 16; + +int Y_STEP_PIN = 9; +int Y_DIR_PIN = 3; +int Y_ENABLE_PIN = -1; +int Y_MIN_PIN = 12; +int Y_MAX_PIN = 13; + +int Z_STEP_PIN = 15; +int Z_DIR_PIN = -1; +int Z_ENABLE_PIN = -1; +int Z_MIN_PIN = -1; +int Z_MAX_PIN = -1; +int Z_ENABLE_SERVO = 1; + +#define COMMAND_SIZE 128 + +char commands[COMMAND_SIZE]; +byte serial_count; +int no_data = 0; + +Servo servo; + +int currentPosServo = 90; +int targetPosServo = 90; +bool comment = false; +void setup() +{ + //Do startup stuff here + Serial.begin(115200); + if(Z_ENABLE_SERVO==1){ + servo.attach(Z_STEP_PIN); + } + //other initialization. + init_process_string(); + init_steppers(); + process_string("G90",3);//Absolute Position + Serial.println("start"); +} + +void loop() +{ + + char c; + //read in characters if we got them. + if (Serial.available() > 0) + { + c = Serial.read(); + no_data = 0; + //newlines are ends of commands. + if (c != '\n') + { + if(c==0x18){ + Serial.println("Grbl 1.0"); + }else{ + if (c == '('){ + comment = true; + } + // If we're not in comment mode, add it to our array. + if (!comment) + { + commands[serial_count] = c; + serial_count++; + } + if (c == ')'){ + comment = false; // End of comment - start listening again + } + } + + } + }else + { + no_data++; + delayMicroseconds(100); + + //if theres a pause or we got a real command, do it + if (serial_count && (c == '\n' || no_data > 100)) + { + //process our command! + process_string(commands, serial_count); + //clear command. + init_process_string(); + } + + //no data? turn off steppers + if (no_data > 1000){ + disable_steppers(); + } + } +// return; +// delay(5); +// int dPos = abs(currentPosServo-targetPosServo); +// if(currentPosServo8?6:1; +// }else if(currentPosServo>targetPosServo){ +// currentPosServo -= dPos>8?6:1; +// } + + +} diff --git a/GCodeParser/process_string.ino b/GCodeParser/process_string.ino new file mode 100644 index 0000000..665ea61 --- /dev/null +++ b/GCodeParser/process_string.ino @@ -0,0 +1,488 @@ +// our point structure to make things nice. +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; //0 = incremental; 1 = absolute + +//default to inches for units +float x_units = X_STEPS_PER_MM; +float y_units = Y_STEPS_PER_MM; +float z_units = Z_STEPS_PER_MM; +float curve_section = CURVE_SECTION_MM; + +//our direction vars +byte x_direction = 1; +byte y_direction = 1; +byte z_direction = 1; + +//init our string processing +void init_process_string() +{ + //init our command + for (byte i=0; i 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); + goto_machine_zero(); + 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); + goto_machine_zero(); + 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); + } + } + 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); + } + } + if(has_command('$', instruction, size)){ + + code = search_string('$', instruction, size); + switch(code){ + case 1: + //set XYZ STEP PIN + if (has_command('X', instruction, size)){ + X_STEP_PIN = search_string('X', instruction, size); + pinMode(X_STEP_PIN,OUTPUT); + digitalWrite(X_STEP_PIN,LOW); + } + if (has_command('Y', instruction, size)){ + Y_STEP_PIN = search_string('Y', instruction, size); + pinMode(Y_STEP_PIN,OUTPUT); + digitalWrite(Y_STEP_PIN,LOW); + } + if (has_command('Z', instruction, size)){ + int TEMP_PIN = search_string('Z', instruction, size); + + if(Z_STEP_PIN!=TEMP_PIN){ + Z_STEP_PIN = TEMP_PIN; + if(Z_ENABLE_SERVO==1){ + servo.attach(Z_STEP_PIN); + }else{ + pinMode(Z_STEP_PIN,OUTPUT); + digitalWrite(Z_STEP_PIN,LOW); + } + } + } + break; + case 2: + //set XYZ DIR PIN + if (has_command('X', instruction, size)){ + X_DIR_PIN = search_string('X', instruction, size); + pinMode(X_DIR_PIN,OUTPUT); + digitalWrite(X_DIR_PIN,LOW); + } + if (has_command('Y', instruction, size)){ + Y_DIR_PIN = search_string('Y', instruction, size); + pinMode(Y_DIR_PIN,OUTPUT); + digitalWrite(Y_DIR_PIN,LOW); + } + if (has_command('Z', instruction, size)){ + Z_DIR_PIN = search_string('Z', instruction, size); + pinMode(Z_DIR_PIN,OUTPUT); + digitalWrite(Z_DIR_PIN,LOW); + } + break; + case 3: + //set XYZ Min PIN + if (has_command('X', instruction, size)){ + X_MIN_PIN = search_string('X', instruction, size); + pinMode(X_MIN_PIN,INPUT_PULLUP); + } + if (has_command('Y', instruction, size)){ + Y_MIN_PIN = search_string('Y', instruction, size); + pinMode(Y_MIN_PIN,INPUT_PULLUP); + } + if (has_command('Z', instruction, size)){ + Z_MIN_PIN = search_string('Z', instruction, size); + pinMode(Z_MIN_PIN,INPUT_PULLUP); + } + break; + case 4: + //set XYZ Max PIN + if (has_command('X', instruction, size)){ + X_MAX_PIN = search_string('X', instruction, size); + pinMode(X_MAX_PIN,INPUT_PULLUP); + } + if (has_command('Y', instruction, size)){ + Y_MAX_PIN = search_string('Y', instruction, size); + pinMode(Y_MAX_PIN,INPUT_PULLUP); + } + if (has_command('Z', instruction, size)){ + Z_MAX_PIN = search_string('Z', instruction, size); + pinMode(Z_MAX_PIN,INPUT_PULLUP); + } + break; + case 5: + //ENABLE SERVO MOTOR FOR Z + if(has_command('Z',instruction,size)){ + Z_ENABLE_SERVO = search_string('Z', instruction, size); + + } + break; + case 6: + //set XYZ STEPS PER MM + if (has_command('X', instruction, size)){ + X_STEPS_PER_MM = search_string('X', instruction, size); + x_units = X_STEPS_PER_MM; + Serial.println(x_units); + } + if (has_command('Y', instruction, size)){ + Y_STEPS_PER_MM = search_string('Y', instruction, size); + y_units = Y_STEPS_PER_MM; + } + if (has_command('Z', instruction, size)){ + Z_STEPS_PER_MM = search_string('Z', instruction, size); + z_units = Z_STEPS_PER_MM; + } + break; + case 7: + //set XYZ FEEDRATE + if (has_command('X', instruction, size)){ + FAST_XY_FEEDRATE = search_string('X', instruction, size); + }else if (has_command('Y', instruction, size)){ + FAST_XY_FEEDRATE = search_string('Y', instruction, size); + } + if (has_command('Z', instruction, size)){ + FAST_Z_FEEDRATE = search_string('Z', instruction, size); + } + break; + case 8: + //set XYZ INVERT LIMIT SWITCH + if (has_command('S', instruction, size)){ + SENSORS_INVERTING = search_string('S', instruction, size); + } + break; + } + + } + //tell our host we're done. + if(code==0&&size==1){ + Serial.println("start"); + }else{ + 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= 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) + { + if(Z_ENABLE_SERVO==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; + } + + //calculate delay between steps in microseconds. this is sort of tricky, but not too bad. + //the formula has been condensed to save space. here it is in english: + // distance / feedrate * 60000000.0 = move duration in microseconds + // move duration / master_steps = time between steps for master axis. + + return ((distance * 60000000.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); +}