diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f833a21 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + g++ -std=c++11 gcode.cpp main.cpp Point.cpp -o gcode_time diff --git a/Point.cpp b/Point.cpp new file mode 100644 index 0000000..f5bd7cd --- /dev/null +++ b/Point.cpp @@ -0,0 +1,36 @@ +#include "Point.h" +#include +#include + +Point::Point(double x, double y, double z, double e) +: x(x), y(y), z(z), e(e) +{ +} + +double Point::get_dist(const Point& other) const +{ + double result; + double dx; + double dy; + double dz; + double de; + + dx = other.x - x; + dy = other.y - y; + dz = other.z - z; + de = abs(other.e - e); + + result = sqrt(dx * dx + dy * dy + dz * dz); + + if (0 == result) + { + result = de; + } + + return result; +} + +void Point::print() +{ + printf("X - %10.5f, Y - %10.5f, Z - %10.5f, E - %10.5f", x, y, z, e); +} diff --git a/Point.h b/Point.h new file mode 100644 index 0000000..c60d0be --- /dev/null +++ b/Point.h @@ -0,0 +1,18 @@ +#ifndef GCODE_POINT_HPP_ +#define GCODE_POINT_HPP_ + +class Point +{ +public: + Point(double x = 0, double y = 0, double z = 0, double e = 0); + + double x; + double y; + double z; + double e; + + double get_dist(const Point& other) const; + void print(); +}; + +#endif // GCODE_POINT_HPP_ diff --git a/gcode.cpp b/gcode.cpp new file mode 100644 index 0000000..46e7183 --- /dev/null +++ b/gcode.cpp @@ -0,0 +1,300 @@ +#include "gcode.h" +#include +#include + +#include + +#define DEBUG 0 + +pair extract_argument(const string& str) +{ + pair result; + + result.first = str[0]; + try + { + result.second = stod(str.substr(1)); + } + catch (invalid_argument& e) + { + cout << "Cannot parse double '" << str << "'" << endl; + } + catch (exception& e) + { + cout << "Exception - " << e.what() << endl; + } + + // Ensure capital letters + if ((result.first >= 'a') && (result.first <= 'z')) + { + result.first -= 'a' - 'A'; + } + else if (!((result.first >= 'A') && (result.first <= 'Z'))) + { + cout << "Argument not a letter '" << result.first << "'" << endl; + } + + return result; +} + +// Linear Move +double g1(const vector& line_tokens, Point& pos, double& speed) +{ + double result; + vector::const_iterator it; + pair arg; + Point end; + double distance; + + end = pos; + it = line_tokens.begin(); + for (++it; it != line_tokens.end(); ++it) + { + arg = extract_argument(*it); + + switch (arg.first) + { + // Extruder + case 'E': + end.e = arg.second; + break; + + // Feedrate (Speed) in units/min + case 'F': + speed = arg.second / 60; + break; + + // Laser power + case 'S': + break; + + case 'X': + end.x = arg.second; + break; + + case 'Y': + end.y = arg.second; + break; + + case 'Z': + end.z = arg.second; + break; + + default: + cout << "G1 - Unknown argument '" << arg.first << "'" << endl; + break; + } + } + +#if DEBUG + for (vector::const_iterator it = line_tokens.begin(); it != line_tokens.end(); ++it) + { + cout << *it << " "; + } + cout << endl; + + cout << "Old pos - "; + pos.print(); + cout << endl; + cout << "New pos - "; + end.print(); + cout << endl; +#endif // DEBUG + + result = 0; + // Perform time calc + distance = pos.get_dist(end); +#if DEBUG + cout << "Distance - " << distance << endl; + cout << "Speed - " << speed << endl; +#endif + if (0 != speed) + { + result = distance / speed; + } + + // Our new position + pos = end; + +#if DEBUG + cout << "Time - " << result << endl << endl; +#endif // DEBUG + + return result; +} + +// Dwell +double g4(const vector& line_tokens, Point& pos, double& speed) +{ + double result; + vector::const_iterator it; + pair arg; + + result = 0; + it = line_tokens.begin(); + for (++it; it != line_tokens.end(); ++it) + { + arg = extract_argument(*it); + + switch (arg.first) + { + // P is for miliseconds + case 'P': + result += arg.second / 1000; + break; + + // S is for seconds + case 'S': + result += arg.second; + break; + + default: + cout << "G4 - Unknown argument: '" << arg.first << "'" << endl; + break; + } + } + +#if DEBUG + for (vector::const_iterator it = line_tokens.begin(); it != line_tokens.end(); ++it) + { + cout << *it << " "; + } + cout << endl; + + cout << "Time - " << result << endl << endl; +#endif // DEBUG + + return result; +} + +// Set Units to Milimeters +double g21(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Move to Origin (Home) +double g28(const vector& line_tokens, Point& pos, double& speed) +{ + // Used only at beginning or end so not relevant + return 0; +} + +// Set to Absolute Positioning +double g90(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Set Position +double g92(const vector& line_tokens, Point& pos, double& speed) +{ + vector::const_iterator it; + pair arg; + +#if DEBUG + for (vector::const_iterator it = line_tokens.begin(); it != line_tokens.end(); ++it) + { + cout << *it << " "; + } + cout << endl; + + cout << "Old pos - "; + pos.print(); + cout << endl; +#endif + + it = line_tokens.begin(); + for (++it; it != line_tokens.end(); ++it) + { + arg = extract_argument(*it); + + switch (arg.first) + { + case 'E': + pos.e = arg.second; + break; + + case 'X': + pos.x = arg.second; + break; + + case 'Y': + pos.y = arg.second; + break; + + case 'Z': + pos.z = arg.second; + break; + + default: + cout << "G92 - Unknown argument '" << arg.first << "'" << endl; + break; + } + } + +#if DEBUG + cout << "New pos - "; + pos.print(); + cout << endl << endl; +#endif // DEBUG + + // There's no actual movement + return 0; +} + +// Set extruder to absolute mode +double m82(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Stop idle hold +double m84(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Set Extruder Temperature +double m104(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Fan On +double m106(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Fan Off +double m107(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Set Extruder Temperature and Wait +double m109(const vector& line_tokens, Point& pos, double& speed) +{ + // Assume everything is preheated + return 0; +} + +// Display Message +double m117(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Set Bed Temperature (Fast) +double m140(const vector& line_tokens, Point& pos, double& speed) +{ + return 0; +} + +// Wait for bed temperature to reach target temp +double m190(const vector& line_tokens, Point& pos, double& speed) +{ + // Assume everything is preheated + return 0; +} diff --git a/gcode.h b/gcode.h new file mode 100644 index 0000000..e87e25d --- /dev/null +++ b/gcode.h @@ -0,0 +1,32 @@ +#ifndef GCODE_H_ +#define GCODE_H_ + +#include +#include + +#include "Point.h" + +using namespace std; + +// Typedef of the function pointer +typedef double (*gcode_cmd_t)(const vector&, Point&, double&); + +// All handled gcode commands +double g1(const vector& line_tokens, Point& pos, double& speed); +double g4(const vector& line_tokens, Point& pos, double& speed); +double g21(const vector& line_tokens, Point& pos, double& speed); +double g28(const vector& line_tokens, Point& pos, double& speed); +double g90(const vector& line_tokens, Point& pos, double& speed); +double g92(const vector& line_tokens, Point& pos, double& speed); + +double m82(const vector& line_tokens, Point& pos, double& speed); +double m84(const vector& line_tokens, Point& pos, double& speed); +double m104(const vector& line_tokens, Point& pos, double& speed); +double m106(const vector& line_tokens, Point& pos, double& speed); +double m107(const vector& line_tokens, Point& pos, double& speed); +double m109(const vector& line_tokens, Point& pos, double& speed); +double m117(const vector& line_tokens, Point& pos, double& speed); +double m140(const vector& line_tokens, Point& pos, double& speed); +double m190(const vector& line_tokens, Point& pos, double& speed); + +#endif // GCODE_H_ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..0c5881e --- /dev/null +++ b/main.cpp @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include + +#include "Point.h" +#include "gcode.h" + +using namespace std; + +void usage(char *name) +{ + cout << "Usage: " << name << " [file]" << endl; +} + +bool is_gcode(const string& line) +{ + bool result = true; + + if (line.empty()) + { + result = false; + } + + if (0 == line.find(';')) + { + result = false; + } + + return result; +} + +string& remove_comments(string& str) +{ + size_t pos; + + pos = str.find(';'); + if (string::npos != pos) + { + str.erase(pos); + } + + return str; +} + +vector tokenize_line(string line) +{ + vector result; + size_t pos = 0; + + while (!line.empty()) + { + pos = line.find(' '); + if (string::npos == pos) + { + pos = line.size(); + } + + // Create a token + result.push_back(line.substr(0, pos)); + // Erase the token + line.erase(0, pos); + // Erase the space + line.erase(0, 1); + } + + return result; +} + +void init_map(map& gcode_map) +{ + // Case insensitive + gcode_map["G1"] = g1; + gcode_map["g1"] = g1; + + gcode_map["G4"] = g4; + gcode_map["g4"] = g4; + + gcode_map["G21"] = g21; + gcode_map["g21"] = g21; + + gcode_map["G28"] = g28; + gcode_map["g28"] = g28; + + gcode_map["G90"] = g90; + gcode_map["g90"] = g90; + + gcode_map["G92"] = g92; + gcode_map["g92"] = g92; + + gcode_map["M82"] = m82; + gcode_map["m82"] = m82; + + gcode_map["M84"] = m84; + gcode_map["m84"] = m84; + + gcode_map["M104"] = m104; + gcode_map["m104"] = m104; + + gcode_map["M106"] = m106; + gcode_map["m106"] = m106; + + gcode_map["M107"] = m107; + gcode_map["m107"] = m107; + + gcode_map["M109"] = m109; + gcode_map["m109"] = m109; + + gcode_map["M117"] = m117; + gcode_map["m117"] = m117; + + gcode_map["M140"] = m140; + gcode_map["m140"] = m140; + + gcode_map["M190"] = m190; + gcode_map["m190"] = m190; +} + +void print_time(double sec) +{ + int hours; + int min; + + hours = sec / 3600; + sec -= hours * 3600; + min = sec / 60; + sec -= min * 60; + + printf("%02d:%02d:%02.0f", hours, min, sec); +} + +int main(int argc, char **argv) +{ + ifstream file; + string line; + vector line_tokens; + + map gcode_map; + + Point pos; + double speed; + double total_time; + int hours; + int minutes; + + if (argc < 2) + { + usage(argv[0]); + return -1; + } + + pos.x = 0; + pos.y = 0; + pos.z = 0; + pos.e = 0; + speed = 0; + total_time = 0; + + init_map(gcode_map); + + file.open(argv[1]); + while (!file.eof()) + { + getline(file, line); + if (!is_gcode(remove_comments(line))) + { + continue; + } + line_tokens = tokenize_line(line); + + if (0 != gcode_map.count(line_tokens[0])) + { + total_time += gcode_map[line_tokens[0]](line_tokens, pos, speed); + } + else + { + cout << "Unknown Gcode '" << line_tokens[0] << "'" << endl; + } + } + file.close(); + + cout << "Estimation - "; + print_time(total_time); + cout << endl; + + cout << "Adding 10% - "; + print_time(total_time * 1.1); + cout << endl; + + return 0; +}