📜 ⬆️ ⬇️

Host controller 3D printer in 16 lines in C ++

Although this article is a kind of answer to the 30th line of JS, the reason for its appearance was quite a practical problem.

The other day, when it was necessary to print out the parts, it suddenly turned out that the usual Repetier Host simply does not start, declaring incompatibility with the Mono version (4.26), when it needs> 4.0. Here is such a "cross-platform".

After launching the attached configuration script, something was swaying and installing for a long time, but nothing worked. There was no desire to find out who was guilty and what to do, so I moved on to the next contender for the working tool - Cura. I tried it - it works, but I don’t have to push the print head manually, googled a newer version of Cura - according to reviews, RepRap printers were removed from there, even if you can manually return them, it's pretty ugly for a company that claims it does open source.
')
Well, okay, I decided, because this is just a form for sending G-codes to the serial port, writing it promised to be a quick matter. During the search for these codes, I came across a great program from this article , it was just what I needed, but the decision was already made. And that's what happened:

#include <unistd.h> #include <fcntl.h> #include <stdint.h> #include <FL/Fl_Button.H> #include <FL/Fl_Window.H> #include <FL/Fl_Counter.H> #include <FL/Fl_Widget.H> #include <FL/Fl.H> const char* data[] = { "X move", "G90\nG1 X%.1f F3000\n", "Y move", "G90\nG1 Y%.1f F3000\n", "Z move", "G90\nG1 Z%.1f F3000\n", "Extrude", "G90\nG1 E%.1f F3000\n", "End", "M303 E0 S%.1f\n", "Bed", "M303 E1 S%.1f\n", "X home", "G28 X0\n", "Y home", "G28 Y0\n", "Z home", "G28 Z0\n", "Beep", "M300 S3000 P100\n", "End Off", "M303 E0 S0\n", "Bed Off", "M303 E1 S0\n" }; Fl_Counter* counters[6]; int buff[10]; int main() { Fl_Window window(310, 310, "Host control"); window.begin(); for (int i = 0; i < 12; i++) { Fl_Widget* widget = i < 6 ? (Fl_Widget*) (counters[i] = new Fl_Counter(10, 10 + i * 50, 200, 30, data[i * 2])) : (Fl_Widget*) new Fl_Button(220, 10 + (i - 6) * 50, 80, 30, data[i * 2]); if (i < 6) ((Fl_Counter*) widget)->step(1, 10); widget->user_data((int*) i); widget->callback([](Fl_Widget* w, void* inner) {if (write(buff[9] == 0 ? (buff[9] = open("/dev/ttyUSB0", O_RDWR | O_NONBLOCK | O_NDELAY)) : buff[9], (char*) buff, sprintf((char*) buff, data[1 + 2 * reinterpret_cast<uintptr_t> (inner)], ((Fl_Counter*) w)->value())) > 0 && reinterpret_cast<uintptr_t> (inner) < 9 && reinterpret_cast<uintptr_t> (inner) >= 6) counters[reinterpret_cast<uintptr_t> (inner) - 6]->value(0);}); } window.end(); window.show(); return Fl::run(); } 

data [] is broken for readability only, I consider it as one line. The remaining lines no longer all look good, but their number after several hacks has become a beautiful round number.

As you can see, the data [] lines are divided into pairs name-gcode, which allows you to draw quite a few widgets (buttons and counters) from this data in one loop, sorting through these lines. Both the buttons and the counters transmit the event listener as a lambda expression, but unfortunately FLTK does not understand the real lambda, so capturing variables cannot be done, but you can pass the pointer to the widget, which is then passed to the callback, which is used here . The number of the widget is brought to the pointer, then inside the lambda the pointer is returned back to the integer, and thus the lambda can find out the number of the widget from which it was called.

Further on this number, the gcode from data [] is taken, the number from the lambda argument is substituted if it was called from the counter, and then the code is written to the serial port. In an amicable way, it would be necessary to indicate the data transfer rate, but it coincided that, although the printer understands only 115200, it started up, so it left it. Another hack - int [] was taken as a buffer for sprintf (), which allowed the last element of the array to be used to store the open () file descriptor, which, together with the “lazy” opening, saved a couple of lines.

As a result, there were 12 widgets for 16 lines of code, almost one line per widget, an interesting result. You can compile with g ++ main.cpp -lfltk -o 3dhost, the fltk-devel package should be in the system.

Link to the repository ; I'm not sure that I will be there to finish something up to a full-fledged application, but what the hell is not joking. By the way, in the same way you can control almost any other device via the serial port, only by replacing the codes and the names of the buttons.

Source: https://habr.com/ru/post/321314/


All Articles