void nurbs_start (int p_seen) { reset_nurbs (); int tmp; if(code_seen('U')) du = code_value(); if(code_seen('K')) { tmp = code_value(); knot[0] = tmp; knot[1] = tmp; knot[2] = tmp; } if(code_seen('K')) knot[3] = code_value(); p = p_seen; }
void nurbs_next () { float cx, cy, cw; if (code_seen('X')) cx = code_value (); if (code_seen('Y')) cy = code_value (); if (code_seen('W')) cw = code_value (); if (code_seen('K')) ck = code_value (); push_back (cx, cy, cw, ck); while (u < knot[3]) { nurbs_basis (); nurbs_curve (); nurbs_move (); u += du; } }
void process_commands() // Routine to interpret commands sent over serial { unsigned long codenum; // throwaway variable char *starpos = NULL; if (code_seen('G')) { switch ((int)code_value()) { } } }
void get_coordinates() { if (code_seen('X')) destination_x = (float)code_value() + relative_mode*current_x; else destination_x = current_x; //Are these else lines really needed? if (code_seen('Y')) destination_y = (float)code_value() + relative_mode*current_y; else destination_y = current_y; if (code_seen('Z')) destination_z = (float)code_value() + relative_mode*current_z; else destination_z = current_z; if (code_seen('E')) destination_e = (float)code_value() + (relative_mode_e || relative_mode)*current_e; else destination_e = current_e; if (code_seen('F')) { next_feedrate = code_value(); if (next_feedrate > 0.0) feedrate = next_feedrate; } //Find direction if (destination_x >= current_x) direction_x=1; else direction_x=0; if (destination_y >= current_y) direction_y=1; else direction_y=0; if (destination_z >= current_z) direction_z=1; else direction_z=0; if (destination_e >= current_e) direction_e=1; else direction_e=0; if (min_software_endstops) { if (destination_x < 0) destination_x = 0.0; if (destination_y < 0) destination_y = 0.0; if (destination_z < 0) destination_z = 0.0; } if (max_software_endstops) { if (destination_x > X_MAX_LENGTH) destination_x = X_MAX_LENGTH; if (destination_y > Y_MAX_LENGTH) destination_y = Y_MAX_LENGTH; if (destination_z > Z_MAX_LENGTH) destination_z = Z_MAX_LENGTH; } if (feedrate > max_feedrate) feedrate = max_feedrate; }
void gcode_M100() { static int m100_not_initialized = 1; unsigned char* sp, *ptr; int i, j, n; // // M100 D dumps the free memory block from __brkval to the stack pointer. // malloc() eats memory from the start of the block and the stack grows // up from the bottom of the block. Solid 0xE5's indicate nothing has // used that memory yet. There should not be anything but 0xE5's within // the block of 0xE5's. If there is, that would indicate memory corruption // probably caused by bad pointers. Any unexpected values will be flagged in // the right hand column to help spotting them. // #if ENABLED(M100_FREE_MEMORY_DUMPER) // Disable to remove Dump sub-command if (code_seen('D')) { ptr = (unsigned char*) __brkval; // // We want to start and end the dump on a nice 16 byte boundry even though // the values we are using are not 16 byte aligned. // SERIAL_ECHOPGM("\n__brkval : "); prt_hex_word((unsigned int) ptr); ptr = (unsigned char*)((unsigned long) ptr & 0xfff0); sp = top_of_stack(); SERIAL_ECHOPGM("\nStack Pointer : "); prt_hex_word((unsigned int) sp); SERIAL_ECHOPGM("\n"); sp = (unsigned char*)((unsigned long) sp | 0x000f); n = sp - ptr; // // This is the main loop of the Dump command. // while (ptr < sp) { prt_hex_word((unsigned int) ptr); // Print the address SERIAL_ECHOPGM(":"); for (i = 0; i < 16; i++) { // and 16 data bytes prt_hex_byte(*(ptr + i)); SERIAL_ECHOPGM(" "); delay(2); } SERIAL_ECHO("|"); // now show where non 0xE5's are for (i = 0; i < 16; i++) { delay(2); if (*(ptr + i) == 0xe5) SERIAL_ECHOPGM(" "); else SERIAL_ECHOPGM("?"); } SERIAL_ECHO("\n"); ptr += 16; delay(2); } SERIAL_ECHOLNPGM("Done.\n"); return; } #endif // // M100 F requests the code to return the number of free bytes in the memory pool along with // other vital statistics that define the memory pool. // if (code_seen('F')) { int max_addr = (int) __brkval; int max_cnt = 0; int block_cnt = 0; ptr = (unsigned char*) __brkval; sp = top_of_stack(); n = sp - ptr; // Scan through the range looking for the biggest block of 0xE5's we can find for (i = 0; i < n; i++) { if (*(ptr + i) == (unsigned char) 0xe5) { j = how_many_E5s_are_here((unsigned char*) ptr + i); if (j > 8) { SERIAL_ECHOPAIR("Found ", j); SERIAL_ECHOPGM(" bytes free at 0x"); prt_hex_word((int) ptr + i); SERIAL_ECHOPGM("\n"); i += j; block_cnt++; } if (j > max_cnt) { // We don't do anything with this information yet max_cnt = j; // but we do know where the biggest free memory block is. max_addr = (int) ptr + i; } } } if (block_cnt > 1) SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.\n"); SERIAL_ECHO("\nDone.\n"); return; } // // M100 C x Corrupts x locations in the free memory pool and reports the locations of the corruption. // This is useful to check the correctness of the M100 D and the M100 F commands. // #if ENABLED(M100_FREE_MEMORY_CORRUPTOR) if (code_seen('C')) { int x; // x gets the # of locations to corrupt within the memory pool x = code_value(); SERIAL_ECHOLNPGM("Corrupting free memory block.\n"); ptr = (unsigned char*) __brkval; SERIAL_ECHOPAIR("\n__brkval : ", (long) ptr); ptr += 8; sp = top_of_stack(); SERIAL_ECHOPAIR("\nStack Pointer : ", (long) sp); SERIAL_ECHOLNPGM("\n"); n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that // has altered the stack. j = n / (x + 1); for (i = 1; i <= x; i++) { *(ptr + (i * j)) = i; SERIAL_ECHO("\nCorrupting address: 0x"); prt_hex_word((unsigned int)(ptr + (i * j))); } SERIAL_ECHOLNPGM("\n"); return; } #endif // // M100 I Initializes the free memory pool so it can be watched and prints vital // statistics that define the free memory pool. // if (m100_not_initialized || code_seen('I')) { // If no sub-command is specified, the first time SERIAL_ECHOLNPGM("Initializing free memory block.\n"); // this happens, it will Initialize. ptr = (unsigned char*) __brkval; // Repeated M100 with no sub-command will not destroy the SERIAL_ECHOPAIR("\n__brkval : ", (long) ptr); // state of the initialized free memory pool. ptr += 8; sp = top_of_stack(); SERIAL_ECHOPAIR("\nStack Pointer : ", (long) sp); SERIAL_ECHOLNPGM("\n"); n = sp - ptr - 64; // -64 just to keep us from finding interrupt activity that // has altered the stack. SERIAL_ECHO(n); SERIAL_ECHOLNPGM(" bytes of memory initialized.\n"); for (i = 0; i < n; i++) *(ptr + i) = (unsigned char) 0xe5; for (i = 0; i < n; i++) { if (*(ptr + i) != (unsigned char) 0xe5) { SERIAL_ECHOPAIR("? address : ", (unsigned long) ptr + i); SERIAL_ECHOPAIR("=", *(ptr + i)); SERIAL_ECHOLNPGM("\n"); } } m100_not_initialized = 0; SERIAL_ECHOLNPGM("Done.\n"); return; } return; }
void process_commands() { unsigned long codenum; //throw away variable //char *starpos = NULL; if (code_seen('G')) { switch ((int) code_value()) { case 0: // G0 -> G1 case 1: // G1 if (code_seen('Z')) { codenum = code_value(); penup = codenum > 0; } if (relative_mode) { double newx = 0; double newy = 0; if (code_seen('X')) { newx = code_value(); } if (code_seen('Y')) { newy = code_value(); } gcode_move(newx, newy, !penup, true); } else { double newx = xpos; double newy = ypos; if (code_seen('X')) { newx = code_value(); } if (code_seen('Y')) { newy = code_value(); } gcode_move(newx, newy, !penup, false); } break; case 4: // G4 dwell codenum = 0; if (code_seen('P')) codenum = code_value(); // milliseconds to wait if (code_seen('S')) codenum = code_value() * 1000; // seconds to wait codenum = codenum / 10; while (codenum-- > 0) { wdt_reset(); msleep(10); } break; case 28: //G28 Home all Axis one at a time stepper_move(0, 0); xoff = 0; yoff = 0; break; case 90: // G90 relative_mode = false; break; case 91: // G91 relative_mode = true; break; case 92: // G92 set coords if (code_seen('X')) { xoff = -xpos + code_value(); xpos = 0; } else { xoff = -xpos; xpos = 0; } if (code_seen('Y')) { yoff = -ypos + code_value(); ypos = 0; } else { yoff = -ypos; ypos = 0; } break; } } else if (code_seen('M')) { switch ((int) code_value()) { case 80://power on break; case 106://load paper stepper_load_paper(); break; case 107://unload paper stepper_unload_paper(); break; case 300://S30=down S50=up S255=off if (code_seen('S')) { penup = code_value() > 40; } break; } }//M else { printf("Error:unknown commando\n"); } }
void Planner::autotemp_M109() { autotemp_enabled = code_seen('F'); if (autotemp_enabled) autotemp_factor = code_value(); if (code_seen('S')) autotemp_min = code_value(); if (code_seen('B')) autotemp_max = code_value(); }
void process_commands() { unsigned long codenum; //throw away variable if (code_seen('N')) { gcode_N = code_value_long(); if (gcode_N != gcode_LastN+1 && (strstr(cmdbuffer, "M110") == NULL) ) { gcode_LastN=0; pc.printf("ok"); //if(gcode_N != gcode_LastN+1 && !code_seen("M110") ) { //Hmm, compile size is different between using this vs the line above even though it should be the same thing. Keeping old method. //pc.printf("Serial Error: Line Number is not Last Line Number+1, Last Line:"); //pc.printf("%d\n",gcode_LastN); //FlushSerialRequestResend(); return; } if (code_seen('*')) { int checksum = 0; int count=0; while (cmdbuffer[count] != '*') checksum = checksum^cmdbuffer[count++]; if ( (int)code_value() != checksum) { //pc.printf("Error: checksum mismatch, Last Line:"); //pc.printf("%d\n",gcode_LastN); //FlushSerialRequestResend(); return; } //if no errors, continue parsing } else { //pc.printf("Error: No Checksum with line number, Last Line:"); //pc.printf("%d\n",gcode_LastN); //FlushSerialRequestResend(); return; } gcode_LastN = gcode_N; //if no errors, continue parsing } else { // if we don't receive 'N' but still see '*' if (code_seen('*')) { //pc.printf("Error: No Line Number with checksum, Last Line:"); //pc.printf("%d\n",gcode_LastN); return; } } //continues parsing only if we don't receive any 'N' or '*' or no errors if we do. :) if (code_seen('G')) { switch ((int)code_value()) { case 0: // G0 -> G1 case 1: // G1 reset_timers();//avoid timer overflow after 30 seconds get_coordinates(); // For X Y Z E F x_steps_to_take = abs(destination_x - current_x)*x_steps_per_unit; y_steps_to_take = abs(destination_y - current_y)*y_steps_per_unit; z_steps_to_take = abs(destination_z - current_z)*z_steps_per_unit; e_steps_to_take = abs(destination_e - current_e)*e_steps_per_unit; //printf(" x_steps_to_take:%d\n", x_steps_to_take); time_for_move = max(X_TIME_FOR_MOVE,Y_TIME_FOR_MOVE); time_for_move = max(time_for_move,Z_TIME_FOR_MOVE); time_for_move = max(time_for_move,E_TIME_FOR_MOVE); if (x_steps_to_take) x_interval = time_for_move/x_steps_to_take; if (y_steps_to_take) y_interval = time_for_move/y_steps_to_take; if (z_steps_to_take) z_interval = time_for_move/z_steps_to_take; if (e_steps_to_take) e_interval = time_for_move/e_steps_to_take; x_steps_remaining = x_steps_to_take; y_steps_remaining = y_steps_to_take; z_steps_remaining = z_steps_to_take; e_steps_remaining = e_steps_to_take; if (DEBUGGING) { pc.printf("destination_x: %f\n",destination_x); pc.printf("current_x: %f\n",current_x); pc.printf("x_steps_to_take: %d\n",x_steps_to_take); pc.printf("X_TIME_FOR_MOVE: %f\n",X_TIME_FOR_MOVE); pc.printf("x_interval: %f\n\n",x_interval); pc.printf("destination_y: %f\n",destination_y); pc.printf("current_y: %f\n",current_y); pc.printf("y_steps_to_take: %d\n",y_steps_to_take); pc.printf("Y_TIME_FOR_MOVE: %f\n",Y_TIME_FOR_MOVE); pc.printf("y_interval: %f\n\n",y_interval); pc.printf("destination_z: %f\n",destination_z); pc.printf("current_z: %f\n",current_z); pc.printf("z_steps_to_take: %d\n",z_steps_to_take); pc.printf("Z_TIME_FOR_MOVE: %f\n",Z_TIME_FOR_MOVE); pc.printf("z_interval: %f\n\n",z_interval); pc.printf("destination_e: %f\n",destination_e); pc.printf("current_e: %f\n",current_e); pc.printf("e_steps_to_take: %d\n",e_steps_to_take); pc.printf("E_TIME_FOR_MOVE: %f\n",E_TIME_FOR_MOVE); pc.printf("e_interval: %f\n\n",e_interval); } linear_move(); // make the move ClearToSend(); return; case 4: // G4 dwell codenum = 0; if (code_seen('P')) codenum = code_value(); // milliseconds to wait if (code_seen('S')) codenum = code_value()*1000; // seconds to wait previous_millis_heater = millis(); // keep track of when we started waiting while ((millis() - previous_millis_heater) < codenum ) manage_heater(); //manage heater until time is up break; case 90: // G90 relative_mode = false; break; case 91: // G91 relative_mode = true; break; case 92: // G92 if (code_seen('X')) current_x = code_value(); if (code_seen('Y')) current_y = code_value(); if (code_seen('Z')) current_z = code_value(); if (code_seen('E')) current_e = code_value(); break; case 93: // G93 pc.printf("previous_micros:%d\n", previous_micros); pc.printf("previous_micros_x:%d\n", previous_micros_x); pc.printf("previous_micros_y:%d\n", previous_micros_y); pc.printf("previous_micros_z:%d\n", previous_micros_z); break; } } if (code_seen('M')) { switch ( (int)code_value() ) { case 104: // M104 - set hot-end temp if (code_seen('S')) { target_raw = temp2analog(code_value()); //pc.printf("target_raw: %d\n ", target_raw); } break; case 140: // M140 - set heated-printbed temp if (code_seen('S')) { target_raw1 = temp2analog(code_value()); //pc.printf("target_raw1: %d\n ", target_raw); } break; case 105: // M105 pc.printf("ok T:"); if (TEMP_0_PIN != NC) { pc.printf("%f\n", analog2temp( (p_temp0.read_u16()) )); } else { pc.printf("0.0\n"); } if (!code_seen('N')) return; // If M105 is sent from generated gcode, then it needs a response. break; case 109: // M109 - Wait for heater to reach target. if (code_seen('S')) target_raw = temp2analog(code_value()); previous_millis_heater = millis(); while (current_raw < target_raw) { if ( (millis()-previous_millis_heater) > 1000 ) { //Print Temp Reading every 1 second while heating up. pc.printf("ok T:"); if (TEMP_0_PIN != NC) { pc.printf("%f\n", analog2temp(p_temp0.read_u16())); } else { pc.printf("0.0\n"); } previous_millis_heater = millis(); } manage_heater(); } break; case 106: //M106 Fan On p_fan = 1; break; case 107: //M107 Fan Off p_fan = 0; break; case 80: // M81 - ATX Power On //if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,OUTPUT); //GND break; case 81: // M81 - ATX Power Off //if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); //Floating break; case 82: relative_mode_e = false; break; case 83: relative_mode_e = true; break; case 84: disable_x(); disable_y(); disable_z(); disable_e(); break; case 85: // M85 code_seen('S'); max_inactive_time = code_value()*1000; break; case 86: // M86 If Endstop is Not Activated then Abort Print if (code_seen('X')) { if (X_MIN_PIN != NC) { if ( p_X_min == ENDSTOPS_INVERTING ) { kill(3); } } } if (code_seen('Y')) { if (Y_MIN_PIN != NC) { if ( p_Y_min == ENDSTOPS_INVERTING ) { kill(4); } } } break; case 92: // M92 if (code_seen('X')) x_steps_per_unit = code_value(); if (code_seen('Y')) y_steps_per_unit = code_value(); if (code_seen('Z')) z_steps_per_unit = code_value(); if (code_seen('E')) e_steps_per_unit = code_value(); break; } } ClearToSend(); }
/*---------------------------------------- * * Start the massive Gcode processing loop *----------------------------------------- */ void process_commands() { int result; int motorChannel, motorPower; unsigned long codenum; char *starpos = NULL; if(code_seen('G')) { switch((int)code_value()) { case 0: // G0 -> G1 case 1: // G1 break; case 2: break; case 3: break; case 4: // G4 dwell //LCD_MESSAGEPGM(MSG_DWELL); codenum = 0; if(code_seen('P')) codenum = code_value(); // milliseconds to wait if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait //codenum += millis(); // keep track of when we started waiting previous_millis_cmd = 0;//millis(); while(++previous_millis_cmd < codenum ){ manage_inactivity(); _delay_ms(1); } break; case 5: // G5 - Absolute command motor C<Channel> P<motor power -1000 to 1000> if(!Stopped) { if(code_seen('C')) { motorChannel = code_value(); // motor channel 1,2 if(code_seen('P')) { motorPower = code_value(); // motor power -1000,1000 fault = 0; // clear fault flag motorControl->commandMotorPower(motorChannel, motorPower); } // code P } // code C } // stopped break; case 28: previous_millis_cmd = 0; break; case 90: // G90 break; case 91: // G91 break; case 92: // G92 break; case 99: // G99 start watchdog timer. G99 T<time_in_millis> values are 15,30,60,120,250,500,1000,4000,8000 default 4000 if( code_seen('T') ) { int time_val = code_value(); watchdog_timer = new WatchdogTimer(); watchdog_timer->watchdog_init(time_val); } break; case 100: // G100 reset watchog timer before time interval is expired, otherwise a reset occurs if( watchdog_timer != NULL ) watchdog_timer->watchdog_reset(); break; } // switch } // if code /*------------------------------------- * M Code processing *-------------------------------------- */ else if(code_seen('M')) { switch( (int)code_value() ) { case 0: // M0 Set real time output off realtime_output = 0; break; case 1: // M1 Set real time output on realtime_output = 1; break; case 2: // M2 [C<channel> E<encoder pin>] set smart controller (default) with optional encoder pin per channel motor_status = 0; motorControl = &roboteqDevice; if(code_seen('C')) { channel = code_value(); if(code_seen('E')) { pin_number = code_value(); motorControl->createEncoder(channel, pin_number); } } break; //Set PWM motor driver, map pin to channel, this will check to prevent free running motors during inactivity //For a PWM motor control subsequent G5 commands are affected here. case 3: // M3 P<pin> C<channel> D<direction pin> E<default dir> W<encoder pin> [T<timer mode 0-3>] [R<resolution 8,9,10 bits>] [X<prescale 0-7>] motor_status = 1; pin_number = -1; encode_pin = 0; motorControl = (AbstractMotorControl*)&hBridgeDriver; ((HBridgeDriver*)motorControl)->setMotors((PWM**)&ppwms); ((HBridgeDriver*)motorControl)->setDirectionPins((Digital**)&pdigitals); if(code_seen('P')) pin_number = code_value(); else break; if(code_seen('C')) { channel = code_value(); if( code_seen('D')) dir_pin = code_value(); else break; if( code_seen('E')) dir_default = code_value(); else break; if( code_seen('W')) encode_pin = code_value(); ((HBridgeDriver*)motorControl)->createPWM(channel, pin_number, dir_pin, dir_default, timer_pre, timer_res); if(encode_pin) motorControl->createEncoder(channel, encode_pin); } // code C break; case 4: // BLDC motor // BLDC: lo1,lo2,lo3,hi1,hi2,hi3,hall1,hall2,hall3,enable // hall sensors hall1:bit0,hall2:bit1,hall2:bit2 of commu array offset // BLDC3PhaseSensor* tmotor1 = new BLDC3PhaseSensor(29,31,33,8,9,10,64,65,66); // tmotor2 = new BLDC3PhaseSensor(35,37,39,11,12,13,67,68,69,30); // tmotor1->motor_init(); // tmotor2->Motor_init(); break; case 11: // M11 C<channel> D<duration> Set maximum motor cycle duration for given channel. if( code_seen('C') ) { channel = code_value(); if( code_seen('D') ) motorControl->setDuration(channel, code_value()); } break; case 12: // M12 C<channel> P<offset> set amount to add to G5 for min motor power if( code_seen('C') ) { channel = code_value(); if( code_seen('P')) motorControl->setMinMotorPower(channel, code_value()); } break; case 17: break; case 18: //M18 break; case 31: //M31 take time since the start of the SD print or an M109 command stoptime=0;//millis(); char time[30]; t =(stoptime-starttime)/1000; int sec,min; min=t/60; sec=t%60; sprintf_P(time, PSTR("%i min, %i sec"), min, sec); SERIAL_PGMLN(timeCntrlHdr); SERIAL_PGM("1 "); SERIAL_PORT.println(time); SERIAL_PORT.flush(); //lcd_setstatus(time); //autotempShutdown(); break; case 33: // M33 P<ultrasonic pin> D<min. distance in cm> [E<direction 1- forward facing, 0 - reverse facing sensor>] // link Motor controller to ultrasonic sensor, the sensor must exist via M301 motor_status = 1; pin_number = 0; if(code_seen('P')) { pin_number = code_value(); if( code_seen('D')) dist = code_value(); else break; dir_face = 1; // default forward if( code_seen('E')) dir_face = code_value(); // optional motorControl->linkDistanceSensor((Ultrasonic**)psonics, pin_number, dist, dir_face); } // code_seen = 'P' break; case 35: //M35 - Clear all digital pins for(int i = 0; i < 10; i++) { if(pdigitals[i]) { unassignPin(pdigitals[i]->pin); delete pdigitals[i]; pdigitals[i] = 0; } } break; case 36: //M36 - Clear all analog pins for(int i = 0; i < 10; i++) { if(panalogs[i]) { unassignPin(panalogs[i]->pin); delete panalogs[i]; panalogs[i] = 0; } } break; case 37: //M36 - Clear all PWM pins for(int i = 0; i < 10; i++) { if(ppwms[i]) { unassignPin(ppwms[i]->pin); delete ppwms[i]; ppwms[i] = 0; } } break; case 38: //M38 - Remove PWM pin P<pin> pin_number = -1; if (code_seen('P')) { pin_number = code_value(); if(unassignPin(pin_number) ) { for(int i = 0; i < 10; i++) { if(ppwms[i] && ppwms[i]->pin == pin_number) { delete ppwms[i]; ppwms[i] = 0; } // pwms == pin_number } // i iterate pwm array } // unassign pin } // code P break; case 39: //M39 - Remove Persistent Analog pin P<pin> pin_number = -1; if (code_seen('P')) { pin_number = code_value(); if(unassignPin(pin_number) ) { for(int i = 0; i < 10; i++) { if(panalogs[i] && panalogs[i]->pin == pin_number) { delete panalogs[i]; panalogs[i] = 0; break; } } } } break; case 40: //M40 - Remove persistent digital pin P<pin> pin_number = -1; if (code_seen('P')) { pin_number = code_value(); if(unassignPin(pin_number) ) { for(int i = 0; i < 10; i++) { if(pdigitals[i] && pdigitals[i] == pin_number) { delete pdigitals[i]; pdigitals[i] = 0; break; } } } } break; case 41: //M41 - Create persistent digital pin, Write digital pin HIGH P<pin> (this gives you a 5v source on pin) pin_number = -1; if (code_seen('P')) { pin_number = code_value(); if( assignPin(pin_number) ) { dpin = new Digital(pin_number); dpin->setPin(pin_number); dpin->pinMode(OUTPUT); dpin->digitalWrite(HIGH); for(int i = 0; i < 10; i++) { if(!pdigitals[i]) { pdigitals[i] = dpin; break; } } } else { for(int i = 0; i < 10; i++) { if(pdigitals[i] && pdigitals[i]->pin == pin_number) { pdigitals[i]->setPin(pin_number); pdigitals[i]->pinMode(OUTPUT); pdigitals[i]->digitalWrite(HIGH); break; } } } } break; case 42: //M42 - Create persistent digital pin, Write digital pin LOW P<pin> (This gives you a grounded pin) pin_number = -1; if (code_seen('P')) { pin_number = code_value(); if( assignPin(pin_number) ) { dpin = new Digital(pin_number); dpin->pinMode(OUTPUT); dpin->digitalWrite(LOW); for(int i = 0; i < 10; i++) { if(!pdigitals[i]) { pdigitals[i] = dpin; break; } } } else { for(int i = 0; i < 10; i++) { if(pdigitals[i] && pdigitals[i]->pin == pin_number) { pdigitals[i]->setPin(pin_number); pdigitals[i]->pinMode(OUTPUT); pdigitals[i]->digitalWrite(LOW); break; } } } } break; case 43: // M43 Read from digital pin P<pin> pin_number = -1; if (code_seen('P')) pin_number = code_value(); if( assignPin(pin_number) ) { dpin = new Digital(pin_number); dpin->pinMode(INPUT); int res = dpin->digitalRead(); delete &dpin; unassignPin(pin_number); // reset it since this is a one-shot SERIAL_PGMLN(digitalPinHdr); SERIAL_PGM("1 "); SERIAL_PORT.println(pin_number); SERIAL_PGM("2 "); SERIAL_PORT.println(res); SERIAL_PORT.println(); SERIAL_PORT.flush(); } break; case 44: // M44 -Read digital pin with pullup P<pin> pin_number = -1; if (code_seen('P')) pin_number = code_value(); if( assignPin(pin_number) ) { dpin = new Digital(pin_number); dpin->pinMode(INPUT_PULLUP); int res = dpin->digitalRead(); delete &dpin; unassignPin(pin_number); // reset it since this is a one-shot SERIAL_PGMLN(digitalPinHdr); SERIAL_PGM("1 "); SERIAL_PORT.println(pin_number); SERIAL_PGM("2 "); SERIAL_PORT.println(res); SERIAL_PORT.flush(); } break; // PWM value between 0 and 255, default timer mode is 2; clear on match, default resolution is 8 bits, default prescale is 1 // Prescale: 1,2,4,6,7,8,9 = none, 8, 64, 256, 1024, external falling, external rising // Use M445 to disable pin permanently or use timer more 0 to stop pulse without removing pin assignment case 45: // M45 - set up PWM P<pin> S<power val 0-255> [T<timer mode 0-3>] [R<resolution 8,9,10 bits>] [X<prescale 0-7>] pin_number = -1; if(code_seen('P') ) pin_number = code_value(); else break; if (code_seen('S')) { int pin_status = code_value(); int timer_mode = 2; int timer_res = 8; int timer_pre = 1; if( pin_status < 0 || pin_status > 255) pin_status = 0; // this is a semi-permanent pin assignment so dont add if its already assigned if( assignPin(pin_number) ) { // timer mode 0-3: 0 stop, 1 toggle on compare match, 2 clear on match, 3 set on match (see HardwareTimer) if( code_seen('T') ) { timer_mode = code_value(); if( timer_mode < 0 || timer_mode > 3 ) timer_mode = 0; } // timer bit resolution 8,9, or 10 bits if( code_seen('R')) { timer_res = code_value(); if( timer_res < 8 || timer_res > 10 ) timer_res = 8; } // X - prescale 0-7 for power of 2 if( code_seen('X') ) { timer_pre = code_value(); if( timer_pre < 0 || timer_pre > 7 ) timer_pre = 0; } for(int i = 0; i < 10; i++) { if(ppwms[i] == NULL) { ppin = new PWM(pin_number); ppin->init(pin_number); ppin->setPWMPrescale(timer_pre); ppin->setPWMResolution(timer_res); ppin->pwmWrite(pin_status,timer_mode); // default is 2, clear on match. to turn off, use 0 ppwms[i] = ppin; break; } } } else { // reassign pin with new mode and value for(int i = 0; i < 10; i++) { if(ppwms[i] && ppwms[i]->pin == pin_number) { // timer mode 0-3: 0 stop, 1 toggle on compare match, 2 clear on match, 3 set on match (see HardwareTimer) if( code_seen('T') ) { timer_mode = code_value(); if( timer_mode < 0 || timer_mode > 3 ) timer_mode = 2; // mess up the code get clear on match default } //ppwms[i]->init(); ppwms[i]->pwmWrite(pin_status, timer_mode); break; } } } } break; case 46: // M46 -Read analog pin P<pin> pin_number = -1; if (code_seen('P')) pin_number = code_value(); if( assignPin(pin_number) ) { apin = new Analog(pin_number); int res = apin->analogRead(); res = apin->analogRead(); // de-jitter delete &apin; unassignPin(pin_number); SERIAL_PGMLN(analogPinHdr); SERIAL_PGM("1 "); SERIAL_PORT.println(pin_number); SERIAL_PGM("2 "); SERIAL_PORT.println(res); SERIAL_PORT.flush(); } break; case 80: // M80 - Turn on Power Supply #if defined(PS_ON_PIN) && PS_ON_PIN > -1 SET_OUTPUT(PS_ON_PIN); //GND WRITE(PS_ON_PIN, PS_ON_AWAKE); // If you have a switch on suicide pin, this is useful #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1 SET_OUTPUT(SUICIDE_PIN); WRITE(SUICIDE_PIN, HIGH); #endif #endif break; case 81: // M81 - Turn off Power if( motorControl->isConnected()) motorControl->commandEmergencyStop(); #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1 suicide(); #elif defined(PS_ON_PIN) && PS_ON_PIN > -1 SET_OUTPUT(PS_ON_PIN); WRITE(PS_ON_PIN, PS_ON_ASLEEP); #endif _delay_ms(1000); // Wait 1 sec before switch off break; case 82: break; case 83: break; case 84: // M84 break; case 85: // M85 break; case 92: // M92 break; case 104: // M104 break; case 105 : // M105 SERIAL_PORT.println(); break; case 106: //M106 break; case 107: //M107 break; case 109: // M109 break; case 115: // M115 SERIAL_PGMLN(MSG_M115_REPORT); break; case 117: break; case 114: // M114 break; case 120: // M120 break; case 121: // M121 break; case 119: // M119 break; case 140: // M140 break; case 150: // M150 - set an RGB value byte red; byte grn; byte blu; if(code_seen('R')) red = code_value(); if(code_seen('U')) grn = code_value(); if(code_seen('B')) blu = code_value(); //SendColors(red,grn,blu); break; case 190: // M190 break; case 200: break; case 201: // M201 //reset_acceleration_rates(); break; case 202: // M202 break; case 203: break; case 204: // M204 acceleration T if(code_seen('T')) ;//max_acceleration = code_value(); break; case 205: //M205 advanced settings: maximum travel speed T=travel if(code_seen('T')) ;//maxtravelspeed = code_value(); break; case 206: break; case 207: break; case 208: break; case 209: break; case 218: break; case 220: if(code_seen('S')) { } break; case 221: if(code_seen('S')) { } break; case 226: // M226 P<pin number> S<pin state>- Wait until the specified pin reaches the state required, default is opposite current state if(code_seen('P')) { int pin_number = code_value(); // pin number int pin_state = -1; // required pin state - default is inverted if(code_seen('S')) pin_state = code_value(); // required pin state if( assignPin(pin_number) ) { Digital pn = new Digital(pin_number); pn.pinMode(INPUT); int target; switch(pin_state){ case 1: target = HIGH; break; case 0: target = LOW; break; default: target = !pn.digitalRead(); // opposite of current state break; } // switch while(pn.digitalRead() != target) { manage_inactivity(); } // while delete &pn; unassignPin(pin_number); } // if pin_number } // code seen p break; case 227: // M227 P<pin number> S<pin state>- INPUT_PULLUP Wait until the specified pin reaches the state required, default is opposite current state if(code_seen('P')) { int pin_number = code_value(); // pin number int pin_state = -1; // required pin state - default is inverted if(code_seen('S')) pin_state = code_value(); // required pin state if( assignPin(pin_number) ) { Digital pn = new Digital(pin_number); pn.pinMode(INPUT_PULLUP); int target; switch(pin_state){ case 1: target = HIGH; break; case 0: target = LOW; break; default: target = !pn.digitalRead(); // opposite of current state break; } // switch while(pn.digitalRead() != target) { manage_inactivity(); } // while delete &pn; unassignPin(pin_number); } // if pin_number } // code seen p break; case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/ /* #if defined(PHOTOGRAPH_PIN) && PHOTOGRAPH_PIN > -1 const uint8_t NUM_PULSES=16; const float PULSE_LENGTH=0.01524; for(int i=0; i < NUM_PULSES; i++) { WRITE(PHOTOGRAPH_PIN, HIGH); _delay_ms(PULSE_LENGTH); WRITE(PHOTOGRAPH_PIN, LOW); _delay_ms(PULSE_LENGTH); } delay(7.33); for(int i=0; i < NUM_PULSES; i++) { WRITE(PHOTOGRAPH_PIN, HIGH); _delay_ms(PULSE_LENGTH); WRITE(PHOTOGRAPH_PIN, LOW); _delay_ms(PULSE_LENGTH); } #endif */ break; case 250: break; case 280: break; case 300: // M300 - emit ultrasonic pulse on given pin and return duration P<pin number> uspin = code_seen('P') ? code_value() : 0; if (uspin > 0) { Ultrasonic* upin = new Ultrasonic(uspin); pin_number = upin->getPin(); SERIAL_PGMLN(sonicCntrlHdr); SERIAL_PGM("1 "); // pin SERIAL_PORT.println(pin_number); SERIAL_PGM("2 "); // sequence SERIAL_PORT.println(upin->getRange()); // range delete upin; } break; case 301: // M301 - toggle ultrasonic during inactivity P<pin> // wont assign pin 0 as its sensitive uspin = code_seen('P') ? code_value() : 0; // this is a permanent pin assignment so dont add if its already assigned if( assignPin(uspin) ) { for(int i = 0; i < 10; i++) { if(!psonics[i]) { psonics[i] = new Ultrasonic(uspin); break; } } } break; case 302: // M302 - disable ultrasonic during inactivity P<pin> uspin = code_seen('P') ? code_value() : 0; unassignPin(uspin); for(int i = 0; i < 10; i++) { if(psonics[i] && psonics[i] == uspin) { delete psonics[i]; psonics[i] = 0; break; } } break; case 303: // M303 - toggle analog read during inactivity P<pin> with exclusion range 0-1024 via L<min> H<max> if present // wont assign pin 0 as its sensitive // if optional L and H values exclude readings in that range uspin = code_seen('P') ? code_value() : 0; // this is a permanent pin assignment so dont add if its already assigned if( assignPin(uspin) ) { for(int i = 0; i < 10; i++) { if(!panalogs[i]) { analogRanges[0][i] = code_seen('L') ? code_value() : 0; analogRanges[1][i] = code_seen('H') ? code_value() : 0; panalogs[i] = new Analog(uspin); panalogs[i]->pinMode(INPUT); break; } } } else { // reassign values for assigned pin for(int i = 0; i < 10; i++) { if(panalogs[i] && panalogs[i]->pin == uspin) { analogRanges[0][i] = code_seen('L') ? code_value() : 0; analogRanges[1][i] = code_seen('H') ? code_value() : 0; break; } } } break; case 304:// M304 - toggle analog read INPUT_PULLUP during inactivity P<pin> with exclusion range 0-1024 via L<min> H<max> if present // if optional L and H values exclude readings in that range uspin = code_seen('P') ? code_value() : 0; // this is a permanent pin assignment so dont add if its already assigned if( assignPin(uspin) ) { for(int i = 0; i < 10; i++) { if(!panalogs[i]) { analogRanges[0][i] = code_seen('L') ? code_value() : 0; analogRanges[1][i] = code_seen('H') ? code_value() : 0; panalogs[i] = new Analog(uspin); panalogs[i]->pinMode(INPUT_PULLUP); break; } } } else { // reassign values for assigned pin for(int i = 0; i < 10; i++) { if(panalogs[i] && panalogs[i]->pin == uspin) { analogRanges[0][i] = code_seen('L') ? code_value() : 0; analogRanges[1][i] = code_seen('H') ? code_value() : 0; break; } } } break; case 305: // M305 - toggle digital read during inactivity M305 P<pin> T<target> 0 or 1 for target value, default 0 // wont assign pin 0 as its sensitive // Looks for target value for pin during inactive, if so publish with <digitalpin> header and 1 - pin, 2 - value uspin = code_seen('P') ? code_value() : 0; digitarg = code_seen('T') ? code_value() : 0; // this is a permanent pin assignment so dont add if its already assigned if( assignPin(uspin) ) { for(int i = 0; i < 10; i++) { if(!pdigitals[i]) { pdigitals[i] = new Digital(uspin); pdigitals[i]->pinMode(INPUT); digitalTarget[i] = digitarg; break; } } } else { for(int i = 0; i < 10; i++) { if(pdigitals[i] && pdigitals[i]->pin == uspin) { digitalTarget[i] = digitarg; break; } } } break; case 306:// M306 - INPUT_PULLUP toggle digital read during inactivity M306 P<pin> T<target> 0 or 1 for target value, default 0 // Looks for target value for pin during inactive, if so publish with <digitalpin> header and 1 - pin 2 - value uspin = code_seen('P') ? code_value() : 0; digitarg = code_seen('T') ? code_value() : 0; // this is a permanent pin assignment so dont add if its already assigned if( assignPin(uspin) ) { for(int i = 0; i < 10; i++) { if(!pdigitals[i]) { pdigitals[i] = new Digital(uspin); pdigitals[i]->pinMode(INPUT_PULLUP); digitalTarget[i] = digitarg; break; } } } else { for(int i = 0; i < 10; i++) { if(pdigitals[i] && pdigitals[i]->pin == uspin) { digitalTarget[i] = digitarg; break; } } } break; case 349: // M349 /* if(code_seen('P')) bedKp = code_value(); if(code_seen('I')) bedKi = scalePID_i(code_value()); if(code_seen('D')) bedKd = scalePID_d(code_value()); updatePID(); SERIAL_PROTOCOL(MSG_OK); SERIAL_PROTOCOL(" p:"); SERIAL_PROTOCOL(bedKp); SERIAL_PROTOCOL(" i:"); SERIAL_PROTOCOL(unscalePID_i(bedKi)); SERIAL_PROTOCOL(" d:"); SERIAL_PROTOCOL(unscalePID_d(bedKd)); SERIAL_PROTOCOLLN(""); */ break; case 350: break; case 351: break; case 400: break; case 401: break; case 402: break; case 444: // M444 - set battery warning threshold V<volts*10>!!!!!!!!!!!!!!!!!! REMEMBER ITS TIMES 10 !!!!!!!!!!!!!!!!!! if(code_seen('V')) { BatteryThreshold = code_value(); // times 10!!! } break; case 445: // M445 - Turn off pulsed write pin - disable PWM P<pin> pin_number = -1; if (code_seen('P')) pin_number = code_value(); unassignPin(pin_number); for(int i = 0; i < 10; i++) { if(ppwms[i] && ppwms[i] == pin_number) { ppwms[i]->pwmWrite(0,0); // default is 2, clear on match. to turn off, use 0 delete ppwms[i]; ppwms[i] = 0; break; } } break; case 500: // M500 Store settings in EEPROM Config_StoreSettings(); break; case 501: // M501 Read settings from EEPROM Config_RetrieveSettings(); break; case 502: // M502 Revert to default settings Config_ResetDefault(); break; case 503: // M503 print settings currently in memory Config_PrintSettings(); break; case 540: //if(code_seen('S')) abort_on_endstop_hit = code_value() > 0; break; case 600: break; case 605: break; case 666: break; case 700: // return stats // Check startup - does nothing if bootloader sets MCUSR to 0 mcu = MCUSR; if(mcu & 1) SERIAL_PGMLN(MSG_POWERUP); if(mcu & 2) SERIAL_PGMLN(MSG_EXTERNAL_RESET); if(mcu & 4) SERIAL_PGMLN(MSG_BROWNOUT_RESET); if(mcu & 8) SERIAL_PGMLN(MSG_WATCHDOG_RESET); if(mcu & 32) SERIAL_PGMLN(MSG_SOFTWARE_RESET); MCUSR=0; SERIAL_PGM(VERSION_STRING); #ifdef STRING_VERSION_CONFIG_H #ifdef STRING_CONFIG_H_AUTHOR SERIAL_PGM(MSG_CONFIGURATION_VER); SERIAL_PGM(STRING_VERSION_CONFIG_H); SERIAL_PGM(MSG_AUTHOR); SERIAL_PGMLN(STRING_CONFIG_H_AUTHOR); SERIAL_PGM("Compiled: "); SERIAL_PGM(__DATE__); #endif #endif SERIAL_PGM(MSG_FREE_MEMORY); SERIAL_PORT.println(freeMemory()); SERIAL_PORT.flush(); break; case 701: // Report digital pins in use SERIAL_PGMLN("Digital Pins:"); for(int i = 0; i < 10; i++) { if( pdigitals[i] ) { SERIAL_PORT.print(pdigitals[i]->pin); switch(pdigitals[i]->mode) { case INPUT: SERIAL_PGMLN(" INPUT"); break; case INPUT_PULLUP: SERIAL_PGMLN(" INPUT_PULLUP"); break; case OUTPUT: SERIAL_PGMLN(" OUTPUT"); break; } } } SERIAL_PORT.println(); SERIAL_PORT.flush(); break; case 702: // Report analog pins in use SERIAL_PGMLN("Analog Pins:"); for(int i = 0; i < 10; i++) { if( panalogs[i] ) { SERIAL_PORT.print(panalogs[i]->pin); switch(panalogs[i]->mode) { case INPUT: SERIAL_PGMLN(" INPUT"); break; case INPUT_PULLUP: SERIAL_PGMLN(" INPUT_PULLUP"); break; case OUTPUT: SERIAL_PGMLN(" OUTPUT"); break; } } } SERIAL_PORT.println(); SERIAL_PORT.flush(); break; case 703: // Report ultrasonic pins in use SERIAL_PGMLN("Ultrasonic Pins:"); for(int i = 0; i < 10; i++) { if( psonics[i] ) { SERIAL_PGM("Pin:"); SERIAL_PORT.println(psonics[i]->getPin()); } } SERIAL_PORT.flush(); break; case 704: // Report PWM pins in use SERIAL_PGMLN("PWM Pins:"); for(int i = 0; i < 10; i++) { if( ppwms[i] ) { SERIAL_PGM("Pin:"); SERIAL_PORT.print(ppwms[i]->pin); SERIAL_PGM(" Timer channel:"); SERIAL_PORT.print(ppwms[i]->channel); switch(ppwms[i]->mode) { case INPUT: SERIAL_PGM(" INPUT"); break; case INPUT_PULLUP: SERIAL_PGM(" INPUT_PULLUP"); break; case OUTPUT: SERIAL_PGM(" OUTPUT"); break; } SERIAL_PORT.println(); } SERIAL_PORT.flush(); } break; case 705: // see if it has propulsion attributes declared with M3 as interrupt serviced switch(motor_status) { case 0: SERIAL_PGMLN("Multi Channel Motor Controller:"); break; case 1: SERIAL_PGMLN("H-Bridge Brushed DC Motor Driver(s):"); break; case 2: SERIAL_PGMLN("Brushless DC Motor Driver(s):"); break; } for(int i = 0 ; i < motorControl->getChannels(); i++) { //per channel SERIAL_PGM("Motor channel:"); SERIAL_PORT.print(i+1); SERIAL_PGM(" Min Power:"); SERIAL_PORT.print(motorControl->getMinMotorPower(i+1)); SERIAL_PGM(" Speed:"); SERIAL_PORT.print(motorControl->getMotorSpeed(i+1)); SERIAL_PGM(" Curr. Dir:"); SERIAL_PORT.print(motorControl->getCurrentDirection(i+1)); SERIAL_PGM(" Default. Dir:"); SERIAL_PORT.println(motorControl->getDefaultDirection(i+1)); SERIAL_PGM(" Encoder Pin:"); if(motorControl->getWheelEncoder(i+1)) { SERIAL_PORT.print(motorControl->getWheelEncoder(i+1)->pin); SERIAL_PGM(" Count:"); SERIAL_PORT.print(motorControl->getEncoderCount(i+1)); SERIAL_PGM(" Duration:"); SERIAL_PORT.println(motorControl->getMaxMotorDuration(i+1)); } else { SERIAL_PGMLN("None."); } } SERIAL_PGM("Ultrasonic pins:"); if( motorControl->totalUltrasonics() ) { SERIAL_PORT.println(motorControl->totalUltrasonics()); for(int j = 0; j < motorControl->totalUltrasonics(); j++) { SERIAL_PGM("Pin:"); SERIAL_PORT.print(psonics[motorControl->getUltrasonicIndex(i+1)]->getPin()); SERIAL_PGM(" Facing:"); SERIAL_PORT.print(motorControl->getUltrasonicFacing(i+1)); SERIAL_PGM(" Shutdown cm:"); SERIAL_PORT.println(motorControl->getMinMotorDist(i+1)); } } else { SERIAL_PGMLN("None."); } SERIAL_PORT.flush(); break; case 706: // Report all pins in use for(int i = 0; i < 100; i++) { if( pinAssignment(i) == PIN_ASSIGNED ) { SERIAL_PORT.print(i); SERIAL_PORT.print(','); } } SERIAL_PORT.println(); SERIAL_PORT.flush(); break; case 797: break; case 798: // Report controller status //SERIAL_PGMLN(motorCntrlHdr); if( motorControl->isConnected() ) { for(int i = 0; i < motorControl->getChannels() ; i++ ) { SERIAL_PGM("Motor Channel:"); SERIAL_PORT.println(i+1); char* buf = motorControl->getDriverInfo(i+1); while(*buf) { SERIAL_PORT.print(*buf); buf++; } } } SERIAL_PORT.println(); SERIAL_PORT.flush(); break; case 799: // Reset Motor controller motorControl->commandEmergencyStop(); break; case 800: break; case 801: // IMU prh = new PitchRollHeading(); orient = prh->getPitchRollHeading(); SERIAL_PGMLN(posCntrlHdr); SERIAL_PGM("1 "); SERIAL_PORT.println(orient.pitch); SERIAL_PGM("2 "); SERIAL_PORT.println(orient.roll); SERIAL_PGM("3 "); SERIAL_PORT.println(orient.heading); break; case 802: // Acquire analog pin data M802 Pnn Sxxx Mxxx P=Pin number, S=number readings, M=microseconds per reading. X - pullup. // Publish <dataset> 1 - pin, 2 - reading if( code_seen('P')) { apin = new Analog((uint8_t)code_value()); if( code_seen('X') ) apin->pinMode(INPUT_PULLUP); else apin->pinMode(INPUT); } nread = 0; if( code_seen('S') ) { nread = code_value(); } micros = 0; if( code_seen('M')) { micros = (uint32_t)code_value(); } values = new int(nread); for(int i = 0; i < nread; i++) { *(values+i) = apin->analogRead(); for(int j = 0; j < micros; j++) _delay_us(1); } SERIAL_PGMLN(datasetHdr); SERIAL_PORT.println(); for(int i = 0; i < nread; i++) { SERIAL_PORT.print(i+1); // sequence SERIAL_PORT.print(' '); // 0 element is pin number if( i == 0 ) SERIAL_PORT.println(apin->pin); else SERIAL_PORT.println(*(values+i)); // value } delete values; SERIAL_PORT.println(); SERIAL_PORT.flush(); break; case 803: break; case 907: break; case 908: // M908 Control digital trimpot directly. uint8_t current; if(code_seen('P')) channel=code_value(); if(code_seen('S')) current=code_value(); digitalPotWrite(channel, current); break; case 999: // M999: Reset Stopped = false; //lcd_reset_alert_level(); gcode_LastN = Stopped_gcode_LastN; //FlushSerialRequestResend(); if( watchdog_timer != NULL ) delete watchdog_timer; watchdog_timer = new WatchdogTimer(); watchdog_timer->watchdog_init(15); // 15 ms } // switch m code } else { // if M code SERIAL_PGMLN(MSG_UNKNOWN_COMMAND); //SERIAL_PORT.println(cmdbuffer[bufindr]); } }
/** * This function used to be inline code in G26. But there are so many * parameters it made sense to turn them into static globals and get * this code out of sight of the main routine. */ bool parse_G26_parameters() { extrusion_multiplier = EXTRUSION_MULTIPLIER; retraction_multiplier = RETRACTION_MULTIPLIER; nozzle = NOZZLE; filament_diameter = FILAMENT; layer_height = LAYER_HEIGHT; prime_length = PRIME_LENGTH; bed_temp = BED_TEMP; hotend_temp = HOTEND_TEMP; ooze_amount = OOZE_AMOUNT; prime_flag = 0; keep_heaters_on = false; if (code_seen('B')) { bed_temp = code_value_temp_abs(); if (!WITHIN(bed_temp, 15, 140)) { SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible."); return UBL_ERR; } } if (code_seen('C')) continue_with_closest++; if (code_seen('L')) { layer_height = code_value_linear_units(); if (!WITHIN(layer_height, 0.0, 2.0)) { SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible."); return UBL_ERR; } } if (code_seen('Q')) { if (code_has_value()) { retraction_multiplier = code_value_float(); if (!WITHIN(retraction_multiplier, 0.05, 15.0)) { SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible."); return UBL_ERR; } } else { SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified."); return UBL_ERR; } } if (code_seen('N') || code_seen('n')) { nozzle = code_value_float(); if (!WITHIN(nozzle, 0.1, 1.0)) { SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible."); return UBL_ERR; } } if (code_seen('K')) keep_heaters_on++; if (code_seen('O') && code_has_value()) ooze_amount = code_value_linear_units(); if (code_seen('P')) { if (!code_has_value()) prime_flag = -1; else { prime_flag++; prime_length = code_value_linear_units(); if (!WITHIN(prime_length, 0.0, 25.0)) { SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible."); return UBL_ERR; } } } if (code_seen('F')) { filament_diameter = code_value_linear_units(); if (!WITHIN(filament_diameter, 1.0, 4.0)) { SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible."); return UBL_ERR; } } extrusion_multiplier *= sq(1.75) / sq(filament_diameter); // If we aren't using 1.75mm filament, we need to // scale up or down the length needed to get the // same volume of filament extrusion_multiplier *= filament_diameter * sq(nozzle) / sq(0.3); // Scale up by nozzle size if (code_seen('H')) { hotend_temp = code_value_temp_abs(); if (!WITHIN(hotend_temp, 165, 280)) { SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible."); return UBL_ERR; } } if (code_seen('R')) { randomSeed(millis()); random_deviation = code_has_value() ? code_value_float() : 50.0; } x_pos = current_position[X_AXIS]; y_pos = current_position[Y_AXIS]; if (code_seen('X')) { x_pos = code_value_axis_units(X_AXIS); if (!WITHIN(x_pos, X_MIN_POS, X_MAX_POS)) { SERIAL_PROTOCOLLNPGM("?Specified X coordinate not plausible."); return UBL_ERR; } } else if (code_seen('Y')) { y_pos = code_value_axis_units(Y_AXIS); if (!WITHIN(y_pos, Y_MIN_POS, Y_MAX_POS)) { SERIAL_PROTOCOLLNPGM("?Specified Y coordinate not plausible."); return UBL_ERR; } } /** * We save the question of what to do with the Unified Bed Leveling System's Activation until the very * end. The reason is, if one of the parameters specified up above is incorrect, we don't want to * alter the system's status. We wait until we know everything is correct before altering the state * of the system. */ ubl.state.active = !code_seen('D'); return UBL_OK; }