/* * Author David Florian * Simplified G-code interpreter * * If you decide not to implement optional features you must * comment out the correspondin * g blocks of code */ #define jfs #ifdef otto #include #endif //**** ARDUINO PINS ***** //***** X-Axis ***** #ifdef otto #define X_EN_PIN 22 // Enable #define X_STEP_PIN 23 // Step #define X_DIR_PIN 24 // Direction #define X_CS_PIN 25 // Chip select #define X_LIMIT 41 // Limit Switch #else #define X_STEP_PIN 54 #define X_DIR_PIN 55 #define X_EN_PIN 38 #define X_CS_PIN 53 // EXP2_07_PIN #define X_LIMIT 3 // X_MIN_PIN #endif //***** Y-Axis ***** #ifdef otto #define Y_EN_PIN 26 // Enable #define Y_STEP_PIN 27 // Step #define Y_DIR_PIN 29 // Direction #define Y1_CS_PIN 28 // Chip select #define Y2_CS_PIN 30 // Chip select #define Y_LIMIT 42 // Limit Switch #else #define Y_EN_PIN 56 // Enable #define Y_STEP_PIN 60 // Step #define Y_DIR_PIN 61 // Direction #define Y1_CS_PIN 49 // EXP2_04_PIN #define Y2_CS_PIN 49 // ??? #define Y_LIMIT 14 // Y_MIN_PIN #endif //***** Z-Axis ***** #ifdef otto #define Z_EN_PIN 31 // Enable #define Z_STEP_PIN 32 // Step #define Z_DIR_PIN 33 // Direction #define Z_CS_PIN 34 // Chip select #define Z_LIMIT 45 // Limit Switch #else #define Z_EN_PIN 62 // Enable #define Z_STEP_PIN 46 // Step #define Z_DIR_PIN 48 // Direction #define Z_CS_PIN 40 // Chip select #define Z_LIMIT 18 // Z_MIN_PIN #endif //***** P-Axis ***** #ifdef otto #define P_EN_PIN 62 // Enable #define P_STEP_PIN 36 // Step #define P_DIR_PIN 37 // Direction #define P_CS_PIN 38 // Chip select #else #define P_EN_PIN 24 // E0_ENABLE_PIN #define P_STEP_PIN 26 // E0_STEP_PIN #define P_DIR_PIN 28 // E0_DIR_PIN #define P_CS_PIN 42 // E0_CS_PIN #endif //***** Floating Head ***** #define FLOATING_HEAD 47 // Floating Head Switch //***** Tip Sensors ***** #define X_LASER 44 // Yellow #define Y_LASER 40 // Black //***** Optional LEDs ****** #define LED_SKIRT 5 #define LED_Pipette 4 //***** Optional Buttons ***** #define PLAY_PAUSE_BUTTON 50 #define PLAY_PAUSE_LED 2 // The LEDs in the button can be turned on and off #define ALERT_BUTTON 46 #define ALERT_BUTTON_LED 3 // The LEDs in the button can be turned on and off #ifdef otto //**** STEPPER DRIVERS ***** //***** Configuring TMC2660 Stepper drivers ***** #define R_SENSE 0.1f // Match to your driver // SilentStepStick series use 0.11 // UltiMachine Einsy and Archim2 boards use 0.2 // Panucatt BSD2660 uses 0.1 // Watterott TMC5160 uses 0.075 TMC2660Stepper driverX = TMC2660Stepper(X_CS_PIN, R_SENSE); TMC2660Stepper driverY1 = TMC2660Stepper(Y1_CS_PIN, R_SENSE); TMC2660Stepper driverY2 = TMC2660Stepper(Y2_CS_PIN, R_SENSE); TMC2660Stepper driverZ = TMC2660Stepper(Z_CS_PIN, R_SENSE); TMC2660Stepper driverP = TMC2660Stepper(P_CS_PIN, R_SENSE); #endif #ifdef jfs #define motorInterfaceType 1 #endif //***** Configuring Step/Dir Pins with AccelStepper ***** #include #include #ifdef otto AccelStepper stepperX(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN); AccelStepper stepperY(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN); AccelStepper stepperZ(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN); AccelStepper stepperP(AccelStepper::DRIVER, P_STEP_PIN, P_DIR_PIN); #endif #ifdef jfs AccelStepper stepperX = AccelStepper(motorInterfaceType, X_STEP_PIN, X_DIR_PIN); AccelStepper stepperY = AccelStepper(motorInterfaceType, Y_STEP_PIN, Y_DIR_PIN); AccelStepper stepperZ = AccelStepper(motorInterfaceType, Z_STEP_PIN, Z_DIR_PIN); AccelStepper stepperP = AccelStepper(motorInterfaceType, P_STEP_PIN, P_DIR_PIN); #endif #ifdef otto //***** OPTIONAL LEDs CONFIGURATION ***** #include //These are WS2812 LEDs AKA Neopixels int skirt_leds_num = 14; //Number of LEDs per strip int pipette_leds_num = 8; Adafruit_NeoPixel skirt_leds = Adafruit_NeoPixel(skirt_leds_num, LED_SKIRT, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel pipette_leds = Adafruit_NeoPixel(pipette_leds_num, LED_Pipette, NEO_GRB + NEO_KHZ800); #endif int changeDirection = 1; // ***** Variables for Serial Communication with Computer ***** const byte numChars = 32; char receivedChars[numChars]; char tempChars[numChars]; // temporary array for use when parsing // variables to hold the parsed data char mode[6]; int integerFromPC = 0; float floatFromPC = 0.0; boolean newData = false; //***** Limit Switches ***** //variables to hold the limit switch states boolean homeX; boolean homeY; boolean homeZ; boolean homeP; //***** STEP PER MM ***** //Its important that these values are correct //so that the digital coordinate system = matches real world //Total step per revolution = full steps/rev * microsteps //200 full steps * 16 microsteps = 3200 digital steps int x_steps_mm = 80; int y_steps_mm = 80; int z_steps_mm = 80; int p_steps_mm = 157.5; // variables to hold location data double locX_in_mm; double locY_in_mm; double locZ_in_mm; double locP_in_mm; int locX_in_steps; int locY_in_steps; int locZ_in_steps; int locP_in_steps; #ifdef jfs int locX_max = 27000; int locY_max = -31200; int locZ_max = 4400; #endif // variables to hold LED data int ledR; int ledG; int ledB; void setup() { #ifdef otto SPI.begin(); #endif Serial.begin(9600); while(!Serial); #ifdef otto // Outputs for Chip Select (or SS) SPI Communication pinMode(X_CS_PIN, OUTPUT); pinMode(Y1_CS_PIN, OUTPUT); pinMode(Y2_CS_PIN, OUTPUT); pinMode(Z_CS_PIN, OUTPUT); pinMode(P_CS_PIN, OUTPUT); digitalWrite(X_CS_PIN, HIGH); digitalWrite(Y1_CS_PIN, HIGH); digitalWrite(Y2_CS_PIN, HIGH); digitalWrite(Z_CS_PIN, HIGH); digitalWrite(P_CS_PIN, HIGH); #endif //***** Setting up Drivers ***** #ifdef otto // X-axis Driver driverX.begin(); // Initiate pins and registeries driverX.rms_current(1000); // Set stepper current to 600mA. driverX.microsteps(16); delay(100); // Y-axis Driver 1 driverY1.begin(); // Initiate pins and registeries driverY1.rms_current(1000); // Set stepper current to 600mA. driverY1.microsteps(16); delay(100); // Y-axis Driver 2 driverY2.begin(); // Initiate pins and registeries driverY2.rms_current(1000); // Set stepper current to 600mA. driverY2.microsteps(16); delay(100); // Z-axis Driver driverZ.begin(); // Initiate pins and registeries driverZ.rms_current(400); // Set stepper current to 600mA. driverZ.microsteps(16); delay(100); // P-axis Driver driverP.begin(); // Initiate pins and registeries driverP.rms_current(400); // Set stepper current to 600mA. driverP.microsteps(4); delay(100); #endif //***** Setting up Switches, Sensors, and Buttons ***** pinMode(X_LIMIT, INPUT); pinMode(Y_LIMIT, INPUT); pinMode(Z_LIMIT, INPUT); pinMode(FLOATING_HEAD, INPUT); pinMode(X_LASER, INPUT); pinMode(Y_LASER, INPUT); pinMode(PLAY_PAUSE_BUTTON, INPUT); pinMode(PLAY_PAUSE_LED, OUTPUT); digitalWrite(PLAY_PAUSE_LED, LOW); pinMode(ALERT_BUTTON, INPUT); pinMode(ALERT_BUTTON_LED, OUTPUT); digitalWrite(ALERT_BUTTON_LED, LOW); stepperX.setMaxSpeed(15000); // 100mm/s @ 160 steps/mm stepperX.setAcceleration(10000); // 2000mm/s^2 stepperX.setEnablePin(X_EN_PIN); stepperX.setPinsInverted(false, false, true); // (directionInvert, stepInvert, enableInvert) stepperX.enableOutputs(); stepperY.setMaxSpeed(12000); // 100mm/s @ 80 steps/mm stepperY.setAcceleration(8000); // 2000mm/s^2 stepperY.setEnablePin(Y_EN_PIN); stepperY.setPinsInverted(false, false, true); // (directionInvert, stepInvert, enableInvert) stepperY.enableOutputs(); stepperZ.setMaxSpeed(12000); // 100mm/s @ 80 steps/mm stepperZ.setAcceleration(7000); // 2000mm/s^2 stepperZ.setEnablePin(Z_EN_PIN); stepperZ.setPinsInverted(false, false, true); // (directionInvert, stepInvert, enableInvert) stepperZ.enableOutputs(); stepperP.setMaxSpeed(5000); // 100mm/s @ 80 steps/mm stepperP.setAcceleration(1000); // 2000mm/s^2 stepperP.setEnablePin(P_EN_PIN); stepperP.setPinsInverted(true, false, true); // (directionInvert, stepInvert, enableInvert) stepperP.enableOutputs(); #ifdef jfs pinMode(X_EN_PIN, OUTPUT); // Enable digitalWrite(X_EN_PIN,LOW); pinMode(Y_EN_PIN, OUTPUT); // Enable digitalWrite(Y_EN_PIN,LOW); pinMode(Z_EN_PIN, OUTPUT); // Enable digitalWrite(Z_EN_PIN,LOW); #endif #ifdef otto //***** Turn on LEDs ***** skirt_leds.begin(); for(int i=0;i 0 && newData == false) { rc = Serial.read(); if (recvInProgress == true) { if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string recvInProgress = false; ndx = 0; newData = true; } } else if (rc == startMarker) { recvInProgress = true; } } } //============ void parseData() { // split the data into its parts //***** Poll the current location of the stepper motors ***** locX_in_mm = stepperX.currentPosition() / x_steps_mm; locY_in_mm = stepperY.currentPosition() / y_steps_mm; locZ_in_mm = stepperZ.currentPosition() / z_steps_mm; locP_in_mm = stepperP.currentPosition() / p_steps_mm; char * strtokIndx; // this is used by strtok() as an index strtokIndx = strtok(tempChars," "); strcpy(mode, strtokIndx); strtokIndx = strtok(NULL," "); while (strtokIndx != NULL){ if (strtokIndx[0] == 'X'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); locX_in_mm = atof(strtokIndx); } if (strtokIndx[0] == 'Y'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); locY_in_mm = -atof(strtokIndx); } if (strtokIndx[0] == 'Z'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); locZ_in_mm = atof(strtokIndx); } if (strtokIndx[0] == 'P'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); locP_in_mm = atof(strtokIndx); } if (strtokIndx[0] == 'E'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); locP_in_mm = atof(strtokIndx); } if (strtokIndx[0] == 'R'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); ledR = atoi(strtokIndx); } if (strtokIndx[0] == 'U' || strtokIndx[0] == 'G'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); ledG = atoi(strtokIndx); } if (strtokIndx[0] == 'B'){ memmove(strtokIndx, strtokIndx+1, strlen(strtokIndx)); ledB = atoi(strtokIndx); } strtokIndx = strtok (NULL, " "); } //***** mm to steps conversions ***** locX_in_steps = locX_in_mm * x_steps_mm; #ifdef jfs if (locX_in_steps > locX_max) { Serial.println(" X off limits "); locX_in_steps = locX_max; } #endif locY_in_steps = locY_in_mm * y_steps_mm; #ifdef jfs if (locY_in_steps < locY_max) { Serial.println(" Y off limits "); locY_in_steps = locY_max; } #endif locZ_in_steps = locZ_in_mm * z_steps_mm; #ifdef jfs if (locZ_in_steps > locZ_max) { Serial.println(" Z off limits "); locZ_in_steps = locZ_max; } #endif locP_in_steps = locP_in_mm * p_steps_mm; } //============ void coordinateMove(){ stepperX.setMaxSpeed(2000); stepperX.setAcceleration(1000); stepperY.setMaxSpeed(2000); stepperY.setAcceleration(1000); stepperZ.setMaxSpeed(2000); stepperZ.setAcceleration(1000); if (strcmp(mode, "G1") == 0){ stepperX.moveTo(locX_in_steps); stepperY.moveTo(locY_in_steps); stepperZ.moveTo(locZ_in_steps); stepperP.moveTo(locP_in_steps); stepperX.setMaxSpeed(10000); stepperX.setAcceleration(3000); stepperY.setMaxSpeed(10000); stepperY.setAcceleration(4000); stepperZ.setMaxSpeed(10000); stepperZ.setAcceleration(6000); stepperP.setMaxSpeed(12000); stepperP.setAcceleration(6000); while(stepperX.targetPosition() != stepperX.currentPosition() or stepperY.targetPosition() != stepperY.currentPosition() or stepperZ.targetPosition() != stepperZ.currentPosition() or stepperP.targetPosition() != stepperP.currentPosition()){ stepperX.run(); stepperY.run(); stepperZ.run(); stepperP.run(); delay(0.001); } Serial.println(""); } #ifdef otto //***** M150 - Change LED Color ***** else if (strcmp(mode, "M150") == 0){ for(int i=0;i"); } #endif //***** M1001 - Laser/Mechanical probing of tip ***** else if (strcmp(mode, "M1001") == 0){ //Speeds and accelerations for tip probe move stepperX.setMaxSpeed(5000); stepperX.setAcceleration(2000); stepperY.setMaxSpeed(5000); stepperY.setAcceleration(2000); stepperZ.setMaxSpeed(5000); stepperZ.setAcceleration(500); boolean boolX = false; boolean tipcheckX = false; boolean tipcheckY = false; int coordX = stepperX.currentPosition(); int coordY = stepperY.currentPosition(); int coordXafter; int coordYafter; int laserXmove = coordX - 1600; //Take the current X position and move 1600 steps (20mm) in the -X direction int laserYmove = coordY + 8000; //Take the current Y position and move 8000 steps (20mm) in the +Y direction //Move in the -X direction until laser tripped stepperX.moveTo(laserXmove); Serial.println(stepperX.distanceToGo()); while (boolX == false && stepperX.distanceToGo()!=0) { stepperX.run(); if (digitalRead(X_LASER) != 0){ delay(10); if (digitalRead(X_LASER) != 0){ boolX= true; stepperX.setSpeed(0); coordXafter = stepperX.currentPosition(); stepperX.move(400); //Move 5mm in the X+ direction. Now the pipette tip will be aligned with the tip that was used during the calibration on the motion controller screen. tipcheckX = true; } } } if (tipcheckX == false){ stepperX.move(1600); } //Move back to the X starting point while(stepperX.targetPosition() != stepperX.currentPosition()){ stepperX.run(); } //Move up 10mm because the Y laser is higher stepperZ.move(4000); while(stepperZ.targetPosition() != stepperZ.currentPosition()){ stepperZ.run(); } boolean boolY = false; stepperY.moveTo(laserYmove); while (boolY == false && stepperY.distanceToGo()!=0) { stepperY.run(); if (digitalRead(Y_LASER) != 0){ delay(10); if (digitalRead(Y_LASER) != 0){ boolY= true; stepperY.setSpeed(0); Serial.println(stepperY.distanceToGo()); coordYafter = stepperY.currentPosition(); stepperY.move(-2000); //Move 5mm in the Y- direction. Now the pipette tip will be aligned with the tip that was used during the calibration on the motion controller screen. tipcheckY = true; } } } if (tipcheckY == false){ stepperY.move(-8000); } stepperZ.move(-4000); while(stepperY.targetPosition() != stepperY.currentPosition() or stepperZ.targetPosition() != stepperZ.currentPosition()){ stepperY.run(); stepperZ.run(); } if (tipcheckY == false || tipcheckX == false){ Serial.println(""); } else{ Serial.println(""); } } else if (strcmp(mode, "J2") == 0){ Serial.print("X Position "); Serial.println( stepperX.currentPosition()); Serial.print("Y Position "); Serial.println( stepperY.currentPosition()); Serial.print("Z Position "); Serial.println( stepperZ.currentPosition()); } else if (strcmp(mode, "JZ") == 0){ //Homing Z at min stepperZ.setMaxSpeed(5000); stepperZ.setAcceleration(2000); int initial_homing = stepperZ.currentPosition(); homeZ = false; while (homeZ == false){ initial_homing--; stepperZ.moveTo(initial_homing); stepperZ.run(); if (digitalRead(Z_LIMIT) != 1) { delay(1); if (digitalRead(Z_LIMIT) !=1){ homeZ = true; } } } stepperZ.setMaxSpeed(10000); stepperZ.setAcceleration(5000); stepperZ.setCurrentPosition(0); stepperP.setCurrentPosition(0); Serial.println(""); } //***** G28 - Homing Cycle ***** // For this code to work as written the limit switches must be located at // X - Mininum // Y - Minimun // Z - Minimun else if (strcmp(mode, "G28") == 0){ //Homing X at min stepperX.setMaxSpeed(5000); stepperX.setAcceleration(2000); int initial_homing = stepperX.currentPosition(); homeX = false; while (homeX == false){ initial_homing--; stepperX.moveTo(initial_homing); stepperX.run(); if (digitalRead(X_LIMIT) != 1) { delay(1); if (digitalRead(X_LIMIT) !=1){ homeX = true; } } } stepperX.setMaxSpeed(10000); stepperX.setAcceleration(5000); stepperX.setCurrentPosition(0); //Homing Y at min stepperY.setMaxSpeed(5000); stepperY.setAcceleration(2000); initial_homing = stepperY.currentPosition(); homeY = false; while (homeY == false){ initial_homing++; stepperY.moveTo(initial_homing); stepperY.run(); if (digitalRead(Y_LIMIT) != 1) { delay(1); if (digitalRead(Y_LIMIT) !=1){ homeY = true; } } } stepperY.setMaxSpeed(10000); stepperY.setAcceleration(5000); stepperY.setCurrentPosition(0); //Homing Z at min stepperZ.setMaxSpeed(5000); stepperZ.setAcceleration(2000); initial_homing = stepperZ.currentPosition(); homeZ = false; while (homeZ == false){ initial_homing--; stepperZ.moveTo(initial_homing); stepperZ.run(); if (digitalRead(Z_LIMIT) != 1) { delay(1); if (digitalRead(Z_LIMIT) !=1){ homeZ = true; } } } stepperZ.setMaxSpeed(10000); stepperZ.setAcceleration(5000); stepperZ.setCurrentPosition(0); stepperP.setCurrentPosition(0); Serial.println(""); } //########Grab Tip######### else if (strcmp(mode, "G38") == 0){ //Move down until Floating head limit switch is triggered //The limit switch trig is debounced (50ms) int tipStatus = 0; int tipStepCount = stepperZ.currentPosition(); int positionBeforeTip = stepperZ.currentPosition(); stepperZ.setMaxSpeed(6000); stepperZ.setAcceleration(2000); while (tipStatus == 0){ if (digitalRead(FLOATING_HEAD) != 0){ stepperZ.setSpeed(0); stepperZ.moveTo(stepperZ.currentPosition()); tipStatus = 1; } else { tipStepCount--; stepperZ.moveTo(tipStepCount); } stepperZ.run(); } stepperZ.moveTo(positionBeforeTip); while(stepperZ.targetPosition() != stepperZ.currentPosition()){ stepperZ.run(); } Serial.println(""); } }