Commit da19d06e authored by MagoKimbra's avatar MagoKimbra

Update V4.2.7

Add M408 Json Output
parent ac4ce4e2
......@@ -4,8 +4,8 @@
2. Download the MarlinKimbra firmware
https://github.com/MagoKimbra/MarlinKimbra
Use the "Download Zip" button on the right.
3. Some boards require special files and/or libraries from the ArduinoAddons directory.
4. Start the arduino IDE 1.6.7.
3. Some boards require special files and/or libraries from the Arduino directory.
4. Start the arduino IDE
5. Select File -> Preferences -> Compiler warning and select none
6. Select Tools -> Board -> Arduino Mega 2560 or your microcontroller
7. Select the correct serial port in Tools ->Serial Port
......
......@@ -42,7 +42,7 @@
* M29 - Stop SD write
* M30 - Delete file from SD (M30 filename.g)
* M31 - Output time since last M109 or SD card start to serial
* M32 - Select file and start SD print (Can be used when printing from SD card)
* M32 - Make directory
* M42 - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used.
* M49 - Z probe repetability test
* M80 - Turn on Power Supply
......@@ -71,6 +71,11 @@
* M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M140 - Set bed target temp
* M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
* M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
* M163 - Set a single proportion for a mixing extruder. Requires COLOR_MIXING_EXTRUDER.
* M164 - Save the mix as a virtual extruder. Requires COLOR_MIXING_EXTRUDER and MIXING_VIRTUAL_TOOLS.
* M165 - Set the proportions for a mixing extruder. Use parameters ABCDHI to set the mixing factors. Requires COLOR_MIXING_EXTRUDER.
* M190 - S[xxx] Wait for bed current temp to reach target temp. Waits only when heating - R[xxx] Wait for bed current temp to reach target temp. Waits when heating and cooling
* M200 - D[millimeters]- set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).
* M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000 Z1000 E0 S1000 E1 S1000 E2 S1000 E3 S1000) in mm/sec^2
......@@ -101,6 +106,7 @@
* M405 - Turn on Filament Sensor extrusion control. Optional D[delay in cm] to set delay in centimeters between sensor and extruder
* M406 - Turn off Filament Sensor extrusion control
* M407 - Displays measured filament diameter
* M408 - Report JSON-style response
* M410 - Quickstop. Abort all the planned moves
* M428 - Set the home_offset logically based on the current_position
* M500 - stores paramters in EEPROM
......@@ -112,6 +118,7 @@
* M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
* M605 - Set dual x-carriage movement mode: Smode [ X<duplication x-offset> Rduplication temp offset ]
* M666 - Set z probe offset or Endstop and delta geometry adjustment. M666 L for list command
* M906 - Set motor currents XYZ T0-4 E
* M907 - Set digital trimpot motor current using axis codes.
* M908 - Control digital trimpot directly.
* M928 - Start SD logging (M928 filename.g) - ended by M29
......
### Version 4.2.7
* Add M906 Set motor Currents for ALLIGATOR board
* Add M408 JSON OUTPUT
### Version 4.2.6
* Bug Fix
......
......@@ -70,6 +70,7 @@
* - L6470 motor drivers
* ADVANCED FEATURES:
* - Buffer stuff
* - Report JSON-style response
* - Whatchdog
* - Start / Stop Gcode
*
......@@ -1527,6 +1528,27 @@
/****************************************************************************************/
/*****************************************************************************************
************************************* JSON OUTPUT ***************************************
*****************************************************************************************
* *
* M408: Report JSON-style response *
* Report a JSON-style response by specifying the desired type using the 'S' parameter. *
* The following response types are supported: *
* Type 0 is a short-form response. *
* Type 1 is like type 0 except that static values are also included. *
* Type 2 is similar to the response provided by the web server for Duet Web Control. *
* Type 3 is an extended version of type 2 which includes some additional parameters *
* that aren't expected to change very frequently. *
* Type 4 is an extended version of type 2 which may be used to poll for current *
* printer statistics. *
* Type 5 reports the current machine configuration. *
* *
*****************************************************************************************/
//#define JSON_OUTPUT
/*****************************************************************************************/
/*****************************************************************************************
*************************************** Whatchdog ***************************************
*****************************************************************************************
......
......@@ -98,7 +98,8 @@
*
* M??? S IDLE_OOZING_enabled
*
*
* ALLIGATOR:
* M906 XYZ T0-4 E Motor current
*
*/
......@@ -256,6 +257,10 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, IDLE_OOZING_enabled);
#endif
#if MB(ALLIGATOR)
EEPROM_WRITE_VAR(i, motor_current);
#endif
char ver2[4] = EEPROM_VERSION;
int j = EEPROM_OFFSET;
EEPROM_WRITE_VAR(j, ver2); // validate data
......@@ -406,6 +411,10 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, IDLE_OOZING_enabled);
#endif
#if MB(ALLIGATOR)
EEPROM_READ_VAR(i, motor_current);
#endif
// Call updatePID (similar to when we have processed M301)
updatePID();
......@@ -448,6 +457,10 @@ void Config_ResetDefault() {
float tmp12[] = {0};
#endif
#if MB(ALLIGATOR)
float tmp13[] = MOTOR_CURRENT;
#endif
for (int8_t i = 0; i < 3 + EXTRUDERS; i++) {
short max_i;
max_i = sizeof(tmp1) / sizeof(*tmp1);
......@@ -494,6 +507,13 @@ void Config_ResetDefault() {
hotend_offset[Z_AXIS][i] = 0;
#endif // HOTENDS > 1
}
#if MB(ALLIGATOR)
max_i = sizeof(tmp13) / sizeof(*tmp13);
if(i < max_i)
motor_current[i] = tmp13[i];
else
motor_current[i] = tmp13[max_i - 1];
#endif
}
#if MECH(SCARA)
......@@ -767,15 +787,15 @@ void Config_ResetDefault() {
if (!forReplay) {
ECHO_LM(CFG, "Material heatup parameters:");
}
ECHO_SMV(CFG, " M145 M0 H", plaPreheatHotendTemp);
ECHO_SMV(CFG, " M145 S0 H", plaPreheatHotendTemp);
ECHO_MV(" B", plaPreheatHPBTemp);
ECHO_MV(" F", plaPreheatFanSpeed);
ECHO_EM(" (Material PLA)");
ECHO_SMV(CFG, " M145 M1 H", absPreheatHotendTemp);
ECHO_SMV(CFG, " M145 S1 H", absPreheatHotendTemp);
ECHO_MV(" B", absPreheatHPBTemp);
ECHO_MV(" F", absPreheatFanSpeed);
ECHO_EM(" (Material ABS)");
ECHO_SMV(CFG, " M145 M2 H", gumPreheatHotendTemp);
ECHO_SMV(CFG, " M145 S2 H", gumPreheatHotendTemp);
ECHO_MV(" B", gumPreheatHPBTemp);
ECHO_MV(" F", gumPreheatFanSpeed);
ECHO_EM(" (Material GUM)");
......@@ -786,7 +806,7 @@ void Config_ResetDefault() {
ECHO_LM(CFG, "PID settings:");
}
#if ENABLED(PIDTEMP)
for (int8_t h = 0; h < HOTENDS; h++) {
for (uint8_t h = 0; h < HOTENDS; h++) {
ECHO_SMV(CFG, " M301 H", h);
ECHO_MV(" P", PID_PARAM(Kp, h));
ECHO_MV(" I", unscalePID_i(PID_PARAM(Ki, h)));
......@@ -858,6 +878,22 @@ void Config_ResetDefault() {
}
}
#if MB(ALLIGATOR)
if (!forReplay) {
ECHO_LM(CFG, "Current:");
}
ECHO_SMV(CFG, " M906 X", motor_current[X_AXIS]);
ECHO_MV(" Y", motor_current[Y_AXIS]);
ECHO_MV(" Z", motor_current[Z_AXIS]);
ECHO_EMV(" E", motor_current[E_AXIS]);
#if DRIVER_EXTRUDERS > 1
for (uint8_t i = 1; i < DRIVER_EXTRUDERS; i++) {
ECHO_SMV(CFG, " M906 T", i);
ECHO_EMV(" E", motor_current[E_AXIS + i]);
}
#endif // DRIVER_EXTRUDERS > 1
#endif // ALLIGATOR
ConfigSD_PrintSettings(forReplay);
}
......
#ifndef CONFIGURATION_VERSION_H
#define CONFIGURATION_VERSION_H
#define SHORT_BUILD_VERSION "4.2.6_dev"
#define BUILD_VERSION "MK_" SHORT_BUILD_VERSION
#define FIRMWARE_NAME "MK"
#define SHORT_BUILD_VERSION "4.2.7_dev"
#define BUILD_VERSION FIRMWARE_NAME "_" SHORT_BUILD_VERSION
#define STRING_DISTRIBUTION_DATE __DATE__ " " __TIME__ // build date and time
// It might also be appropriate to define a location where additional information can be found
#define FIRMWARE_URL "https://github.com/MagoKimbra/MarlinKimbra"
#endif
\ No newline at end of file
#endif
......@@ -154,6 +154,7 @@
* M405 - Turn on Filament Sensor extrusion control. Optional D<delay in cm> to set delay in centimeters between sensor and extruder
* M406 - Turn off Filament Sensor extrusion control
* M407 - Display measured filament diameter
* M408 - Report JSON-style response
* M410 - Quickstop. Abort all the planned moves
* M428 - Set the home_offset logically based on the current_position
* M500 - Store parameters in EEPROM
......@@ -166,6 +167,7 @@
* M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
* M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
* M666 - Set z probe offset or Endstop and delta geometry adjustment
* M906 - Set motor currents XYZ T0-4 E
* M907 - Set digital trimpot motor current using axis codes.
* M908 - Control digital trimpot directly.
*
......@@ -206,9 +208,6 @@
#include <LiquidCrystal.h> // library for character LCD
#endif
#endif
#if ENABLED(NEXTION)
#include <Nextion.h>
#endif
#if HAS(DIGIPOTSS)
#include <SPI.h>
#endif
This diff is collapsed.
......@@ -217,6 +217,10 @@ extern uint8_t active_extruder;
extern uint8_t previous_extruder;
extern uint8_t active_driver;
#if MB(ALLIGATOR)
extern float motor_current[DRIVER_EXTRUDERS + 3];
#endif
#if ENABLED(DIGIPOT_I2C)
extern void digipot_i2c_set_current( int channel, float current );
extern void digipot_i2c_init();
......
This diff is collapsed.
......@@ -1374,7 +1374,6 @@ void digipot_init() {
#endif
#if MB(ALLIGATOR)
const float motor_current[] = MOTOR_CURRENT;
unsigned int digipot_motor = 0;
for (uint8_t i = 0; i < 3 + DRIVER_EXTRUDERS; i++) {
digipot_motor = 255 * (motor_current[i] / 2.5);
......
......@@ -52,9 +52,9 @@ void vector_3::normalize() {
}
void vector_3::apply_rotation(matrix_3x3 matrix) {
float resultX = x * matrix.matrix[3 * 0 + 0] + y * matrix.matrix[3 * 1 + 0] + z * matrix.matrix[3 * 2 + 0];
float resultY = x * matrix.matrix[3 * 0 + 1] + y * matrix.matrix[3 * 1 + 1] + z * matrix.matrix[3 * 2 + 1];
float resultZ = x * matrix.matrix[3 * 0 + 2] + y * matrix.matrix[3 * 1 + 2] + z * matrix.matrix[3 * 2 + 2];
float resultX = x * matrix.matrix[0][0] + y * matrix.matrix[1][0] + z * matrix.matrix[2][0];
float resultY = x * matrix.matrix[0][1] + y * matrix.matrix[1][1] + z * matrix.matrix[2][1];
float resultZ = x * matrix.matrix[0][2] + y * matrix.matrix[1][2] + z * matrix.matrix[2][2];
x = resultX;
y = resultY;
z = resultZ;
......@@ -80,17 +80,17 @@ matrix_3x3 matrix_3x3::create_from_rows(vector_3 row_0, vector_3 row_1, vector_3
//row_1.debug("row_1");
//row_2.debug("row_2");
matrix_3x3 new_matrix;
new_matrix.matrix[0] = row_0.x; new_matrix.matrix[1] = row_0.y; new_matrix.matrix[2] = row_0.z;
new_matrix.matrix[3] = row_1.x; new_matrix.matrix[4] = row_1.y; new_matrix.matrix[5] = row_1.z;
new_matrix.matrix[6] = row_2.x; new_matrix.matrix[7] = row_2.y; new_matrix.matrix[8] = row_2.z;
new_matrix.matrix[0][0] = row_0.x; new_matrix.matrix[0][1] = row_0.y; new_matrix.matrix[0][2] = row_0.z;
new_matrix.matrix[1][0] = row_1.x; new_matrix.matrix[1][1] = row_1.y; new_matrix.matrix[1][2] = row_1.z;
new_matrix.matrix[2][0] = row_2.x; new_matrix.matrix[2][1] = row_2.y; new_matrix.matrix[2][2] = row_2.z;
//new_matrix.debug("new_matrix");
return new_matrix;
}
void matrix_3x3::set_to_identity() {
matrix[0] = 1; matrix[1] = 0; matrix[2] = 0;
matrix[3] = 0; matrix[4] = 1; matrix[5] = 0;
matrix[6] = 0; matrix[7] = 0; matrix[8] = 1;
matrix[0][0] = 1; matrix[0][1] = 0; matrix[0][2] = 0;
matrix[1][0] = 0; matrix[1][1] = 1; matrix[1][2] = 0;
matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 1;
}
matrix_3x3 matrix_3x3::create_look_at(vector_3 target) {
......@@ -111,22 +111,20 @@ matrix_3x3 matrix_3x3::create_look_at(vector_3 target) {
matrix_3x3 matrix_3x3::transpose(matrix_3x3 original) {
matrix_3x3 new_matrix;
new_matrix.matrix[0] = original.matrix[0]; new_matrix.matrix[1] = original.matrix[3]; new_matrix.matrix[2] = original.matrix[6];
new_matrix.matrix[3] = original.matrix[1]; new_matrix.matrix[4] = original.matrix[4]; new_matrix.matrix[5] = original.matrix[7];
new_matrix.matrix[6] = original.matrix[2]; new_matrix.matrix[7] = original.matrix[5]; new_matrix.matrix[8] = original.matrix[8];
new_matrix.matrix[0][0] = original.matrix[0][0]; new_matrix.matrix[0][1] = original.matrix[1][0]; new_matrix.matrix[0][2] = original.matrix[2][0];
new_matrix.matrix[1][0] = original.matrix[0][1]; new_matrix.matrix[1][1] = original.matrix[1][1]; new_matrix.matrix[1][2] = original.matrix[2][1];
new_matrix.matrix[2][0] = original.matrix[0][2]; new_matrix.matrix[2][1] = original.matrix[1][2]; new_matrix.matrix[2][2] = original.matrix[2][2];
return new_matrix;
}
void matrix_3x3::debug(const char title[]) {
ECHO_LT(DB, title);
int count = 0;
for (int i = 0; i < 3; i++) {
for (uint8_t i = 0; i < 3; i++) {
ECHO_S(DB);
for (int j = 0; j < 3; j++) {
if (matrix[count] >= 0.0) ECHO_C('+');
ECHO_V(matrix[count], 6);
for (uint8_t j = 0; j < 3; j++) {
if (matrix[i][j] >= 0.0) ECHO_C('+');
ECHO_V(matrix[i][j], 6);
ECHO_C(' ');
count++;
}
ECHO_E;
}
......
......@@ -43,7 +43,7 @@ struct vector_3 {
};
struct matrix_3x3 {
float matrix[9];
float matrix[3][3];
static matrix_3x3 create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2);
static matrix_3x3 create_look_at(vector_3 target);
......
......@@ -677,11 +677,11 @@ uint8_t SdBaseFile::lsRecursive(SdBaseFile* parent, uint8_t level, char* findFil
ECHO_T(fullName);
ECHO_C('/');
}
#if JSON_OUTPUT
#ifdef JSON_OUTPUT
if (isJson) {
if (!firstFile) ECHO_C(',');
ECHO_C('"'); ECHO_C('*');
SDCard::printEscapeChars(tempLongFilename);
CardReader::printEscapeChars(tempLongFilename);
ECHO_C('"');
firstFile = false;
}
......@@ -731,11 +731,11 @@ uint8_t SdBaseFile::lsRecursive(SdBaseFile* parent, uint8_t level, char* findFil
ECHO_T(fullName);
ECHO_C('/');
}
#if JSON_OUTPUT
#ifdef JSON_OUTPUT
if (isJson) {
if (!firstFile) ECHO_C(',');
ECHO_C('"');
SDCard::printEscapeChars(tempLongFilename);
CardReader::printEscapeChars(tempLongFilename);
ECHO_C('"');
firstFile = false;
}
......@@ -779,7 +779,7 @@ void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
lsRecursive(&parent, 0, NULL, NULL, false);
}
#if JSON_OUTPUT
#ifdef JSON_OUTPUT
void SdBaseFile::lsJSON() {
SdBaseFile parent;
rewind();
......
......@@ -1985,7 +1985,7 @@ class SdBaseFile {
static bool remove(SdBaseFile& dirFile, const char* path) // NOLINT
__attribute__((error("use remove(&dirFile, path)")));
#endif // ALLOW_DEPRECATED_FUNCTIONS
#if JSON_OUTPUT
#ifdef JSON_OUTPUT
void lsJSON();
#endif
};
......
......@@ -8,7 +8,7 @@ char tempLongFilename[LONG_FILENAME_LENGTH + 1];
char fullName[LONG_FILENAME_LENGTH * SD_MAX_FOLDER_DEPTH + SD_MAX_FOLDER_DEPTH + 1];
CardReader::CardReader() {
filesize = 0;
fileSize = 0;
sdpos = 0;
sdprinting = false;
cardOK = false;
......@@ -170,8 +170,11 @@ bool CardReader::selectFile(const char* filename, bool silent/*=false*/) {
ECHO_MT(SERIAL_SD_FILE_OPENED, oldP);
ECHO_EMV(SERIAL_SD_SIZE, file.fileSize());
}
#if ENABLED(JSON_OUTPUT)
parsejson(file);
#endif
sdpos = 0;
filesize = file.fileSize();
fileSize = file.fileSize();
ECHO_EM(SERIAL_SD_FILE_SELECTED);
return true;
}
......@@ -184,7 +187,7 @@ bool CardReader::selectFile(const char* filename, bool silent/*=false*/) {
void CardReader::printStatus() {
if (cardOK) {
ECHO_MV(SERIAL_SD_PRINTING_BYTE, sdpos);
ECHO_EMV(SERIAL_SD_SLASH, filesize);
ECHO_EMV(SERIAL_SD_SLASH, fileSize);
}
else
ECHO_EM(SERIAL_SD_NOT_PRINTING);
......@@ -333,6 +336,250 @@ void CardReader::setlast() {
curDir = &workDir;
}
// --------------------------------------------------------------- //
// Code that gets gcode information is adapted from RepRapFirmware //
// Originally licenced under GPL //
// Authors: reprappro, dc42, dcnewman, others //
// Source: https://github.com/dcnewman/RepRapFirmware //
// Copy date: 27 FEB 2016 //
// --------------------------------------------------------------- //
void CardReader::parsejson(SdBaseFile &file) {
fileSize = file.fileSize();
filamentNeeded = 0.0;
objectHeight = 0.0;
firstlayerHeight = 0.0;
layerHeight = 0.0;
if (!file.isOpen()) return;
bool genByFound = false, firstlayerHeightFound = false, layerHeightFound = false, filamentNeedFound = false;
#if CPU_ARCH==ARCH_AVR
#define GCI_BUF_SIZE 120
#else
#define GCI_BUF_SIZE 1024
#endif
// READ 4KB FROM THE BEGINNING
char buf[GCI_BUF_SIZE];
for (int i = 0; i < 4096; i += GCI_BUF_SIZE - 50) {
if(!file.seekSet(i)) break;
file.read(buf, GCI_BUF_SIZE);
if (!genByFound && findGeneratedBy(buf, generatedBy)) genByFound = true;
if (!firstlayerHeightFound && findFirstLayerHeight(buf, firstlayerHeight)) firstlayerHeightFound = true;
if (!layerHeightFound && findLayerHeight(buf, layerHeight)) layerHeightFound = true;
if (!filamentNeedFound && findFilamentNeed(buf, filamentNeeded)) filamentNeedFound = true;
if(genByFound && layerHeightFound && filamentNeedFound) goto get_objectHeight;
}
// READ 4KB FROM END
for (int i = 0; i < 4096; i += GCI_BUF_SIZE - 50) {
if(!file.seekEnd(-4096 + i)) break;
file.read(buf, GCI_BUF_SIZE);
if (!genByFound && findGeneratedBy(buf, generatedBy)) genByFound = true;
if (!firstlayerHeightFound && findFirstLayerHeight(buf, firstlayerHeight)) firstlayerHeightFound = true;
if (!layerHeightFound && findLayerHeight(buf, layerHeight)) layerHeightFound = true;
if (!filamentNeedFound && findFilamentNeed(buf, filamentNeeded)) filamentNeedFound = true;
if(genByFound && layerHeightFound && filamentNeedFound) goto get_objectHeight;
}
get_objectHeight:
// MOVE FROM END UP IN 1KB BLOCKS UP TO 30KB
for (int i = GCI_BUF_SIZE; i < 30000; i += GCI_BUF_SIZE - 50) {
if(!file.seekEnd(-i)) break;
file.read(buf, GCI_BUF_SIZE);
if (findTotalHeight(buf, objectHeight)) break;
}
file.seekSet(0);
}
void CardReader::printEscapeChars(const char* s) {
for (unsigned int i = 0; i < strlen(s); ++i) {
switch (s[i]) {
case '"':
case '/':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
case '\\':
ECHO_T('\\');
break;
}
ECHO_T(s[i]);
}
}
bool CardReader::findGeneratedBy(char* buf, char* genBy) {
// Slic3r & S3D
const char* generatedByString = PSTR("generated by ");
char* pos = strstr_P(buf, generatedByString);
if (pos) {
pos += strlen_P(generatedByString);
size_t i = 0;
while (i < GENBY_SIZE - 1 && *pos >= ' ') {
char c = *pos++;
if (c == '"' || c == '\\') {
// Need to escape the quote-mark for JSON
if (i > GENBY_SIZE - 3) break;
genBy[i++] = '\\';
}
genBy[i++] = c;
}
genBy[i] = 0;
return true;
}
// CURA
const char* slicedAtString = PSTR(";Sliced at: ");
pos = strstr_P(buf, slicedAtString);
if (pos) {
strcpy_P(genBy, PSTR("Cura"));
return true;
}
// UNKNOWN
strcpy_P(genBy, PSTR("Unknown"));
return false;
}
bool CardReader::findFirstLayerHeight(char* buf, float& firstlayerHeight) {
// SLIC3R
firstlayerHeight = 0;
const char* layerHeightSlic3r = PSTR("; first_layer_height ");
char *pos = strstr_P(buf, layerHeightSlic3r);
if (pos) {
pos += strlen_P(layerHeightSlic3r);
while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
++pos;
}
firstlayerHeight = strtod(pos, NULL);
return true;
}
// CURA
const char* layerHeightCura = PSTR("First layer height: ");
pos = strstr_P(buf, layerHeightCura);
if (pos) {
pos += strlen_P(layerHeightCura);
while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
++pos;
}
firstlayerHeight = strtod(pos, NULL);
return true;
}
return false;
}
bool CardReader::findLayerHeight(char* buf, float& layerHeight) {
// SLIC3R
layerHeight = 0;
const char* layerHeightSlic3r = PSTR("; layer_height ");
char *pos = strstr_P(buf, layerHeightSlic3r);
if (pos) {
pos += strlen_P(layerHeightSlic3r);
while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
++pos;
}
layerHeight = strtod(pos, NULL);
return true;
}
// CURA
const char* layerHeightCura = PSTR("Layer height: ");
pos = strstr_P(buf, layerHeightCura);
if (pos) {
pos += strlen_P(layerHeightCura);
while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
++pos;
}
layerHeight = strtod(pos, NULL);
return true;
}
return false;
}
bool CardReader::findFilamentNeed(char* buf, float& filament) {
const char* filamentUsedStr = PSTR("filament used");
const char* pos = strstr_P(buf, filamentUsedStr);
filament = 0;
if (pos != NULL) {
pos += strlen_P(filamentUsedStr);
while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
++pos; // this allows for " = " from default slic3r comment and ": " from default Cura comment
}
if (isDigit(*pos)) {
char *q;
filament += strtod(pos, &q);
if (*q == 'm' && *(q + 1) != 'm') {
filament *= 1000.0; // Cura outputs filament used in metres not mm
}
}
return true;
}
return false;
}
bool CardReader::findTotalHeight(char* buf, float& height) {
int len = 1024;
bool inComment, inRelativeMode = false;
unsigned int zPos;
for (int i = len - 5; i > 0; i--) {
if (inRelativeMode) {
inRelativeMode = !(buf[i] == 'G' && buf[i + 1] == '9' && buf[i + 2] == '1' && buf[i + 3] <= ' ');
}
else if (buf[i] == 'G') {
// Ignore G0/G1 codes if absolute mode was switched back using G90 (typical for Cura files)
if (buf[i + 1] == '9' && buf[i + 2] == '0' && buf[i + 3] <= ' ') {
inRelativeMode = true;
}
else if ((buf[i + 1] == '0' || buf[i + 1] == '1') && buf[i + 2] == ' ') {
// Look for last "G0/G1 ... Z#HEIGHT#" command as generated by common slicers
// Looks like we found a controlled move, however it could be in a comment, especially when using slic3r 1.1.1
inComment = false;
size_t j = i;
while (j != 0) {
--j;
char c = buf[j];
if (c == '\n' || c == '\r') break;
if (c == ';') {
// It is in a comment, so give up on this one
inComment = true;
break;
}
}
if (inComment) continue;
// Find 'Z' position and grab that value
zPos = 0;
for (int j = i + 3; j < len - 2; j++) {
char c = buf[j];
if (c < ' ') {
// Skip all whitespaces...
while (j < len - 2 && c <= ' ') {
c = buf[++j];
}
// ...to make sure ";End" doesn't follow G0 .. Z#HEIGHT#
if (zPos != 0) {
//debugPrintf("Found at offset %u text: %.100s\n", zPos, &buf[zPos + 1]);
height = strtod(&buf[zPos + 1], NULL);
return true;
}
break;
}
else if (c == ';') break;
else if (c == 'Z') zPos = j;
}
}
}
}
return false;
}
/**
* File parser for KEY->VALUE format from files
*
......
......@@ -9,6 +9,7 @@
/** Total size of the buffer used to store the long filenames */
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * MAX_VFAT_ENTRIES + 1)
#define SHORT_FILENAME_LENGTH 14
#define GENBY_SIZE 16
extern char tempLongFilename[LONG_FILENAME_LENGTH + 1];
extern char fullName[LONG_FILENAME_LENGTH * SD_MAX_FOLDER_DEPTH + SD_MAX_FOLDER_DEPTH + 1];
......@@ -54,28 +55,37 @@ public:
FORCE_INLINE void setIndex(uint32_t newpos) { sdpos = newpos; file.seekSet(sdpos); }
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
FORCE_INLINE bool eof() { return sdpos >= filesize; }
FORCE_INLINE bool eof() { return sdpos >= fileSize; }
FORCE_INLINE int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
FORCE_INLINE uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
FORCE_INLINE uint8_t percentDone() { return (isFileOpen() && fileSize) ? sdpos / ((fileSize + 99) / 100) : 0; }
FORCE_INLINE char* getWorkDirName() { workDir.getFilename(fullName); return fullName; }
//files init.g on the sd card are performed in a row
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
void checkautostart(bool x);
public:
bool saving, sdprinting, cardOK, filenameIsDir;
uint32_t fileSize, sdpos;
float objectHeight, firstlayerHeight, layerHeight, filamentNeeded;
char generatedBy[GENBY_SIZE];
static void printEscapeChars(const char* s);
private:
SdBaseFile root, *curDir, workDir, lastDir, workDirParents[SD_MAX_FOLDER_DEPTH];
Sd2Card card;
uint16_t workDirDepth;
uint32_t filesize;
millis_t next_autostart_ms;
uint32_t sdpos;
uint16_t nrFiles; // counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
LsAction lsAction; //stored for recursion.
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
void lsDive(SdBaseFile parent, const char* const match = NULL);
void parsejson(SdBaseFile &file);
bool findGeneratedBy(char* buf, char* genBy);
bool findFirstLayerHeight(char* buf, float& firstlayerHeight);
bool findLayerHeight(char* buf, float& layerHeight);
bool findFilamentNeed(char* buf, float& filament);
bool findTotalHeight(char* buf, float& objectHeight);
};
extern CardReader card;
......
......@@ -253,9 +253,7 @@ void Servo::detach() {
void Servo::write(int value) {
if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < 0) value = 0;
if (value > 180) value = 180;
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN(), SERVO_MAX());
}
this->writeMicroseconds(value);
}
......@@ -264,18 +262,13 @@ void Servo::writeMicroseconds(int value) {
// calculate and store the values for the given channel
byte channel = this->servoIndex;
if (channel < MAX_SERVOS) { // ensure channel is valid
if (value < SERVO_MIN()) // ensure pulse width is valid
value = SERVO_MIN();
else if (value > SERVO_MAX())
value = SERVO_MAX();
value = value - TRIM_DURATION;
// ensure pulse width is valid
value = constrain(value, SERVO_MIN(), SERVO_MAX()) - TRIM_DURATION;
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead
uint8_t oldSREG = SREG;
cli();
servos[channel].ticks = value;
SREG = oldSREG;
CRITICAL_SECTION_START;
servo_info[channel].ticks = value;
CRITICAL_SECTION_END;
}
}
......
......@@ -1087,7 +1087,7 @@ void tp_init() {
BITSET(TIMSK0, OCIE0B);
// Wait for temperature measurement to settle
delay(250);
delay_ms(250);
#define TEMP_MIN_ROUTINE(NR) \
minttemp[NR] = HEATER_ ## NR ## _MINTEMP; \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment