Close
0%
0%

GUI Programming for a Console Hacker

After 30 years of procedural language programming (i.e. console programming), time to look at event driven programming.

Similar projects worth following
Scope
---------
For myself, writing console programs, especially using command-line arguments and files for input, has worked well. But for other people no doubt, they would prefer a Windows like GUI (i.e. Graphical User Interface).
GUI interfaces are however, event driven which does not work well with the numeric intensive problems that I like to solve. Well that is not true, of course but you need to step up to threaded code at the same time for this (usually). That is one thread for the GUI and one for the numeric intensive code. It not really a big deal (an excuse I suppose).
So okay, other than using Microsoft Visual C (for Windows?), how should I best go about it for a Linux environment.
Most Linux systems use the underlying "X11" library so that is where to start.

AlanX

The Task

Okay, nice to have a task to guide the exploration. So let me build a "gCodeSender" clone for Linux. "gCodeSender" (https://wiki.shapeoko.com/index.php/GcodeSender) was my preferred Windows program for controlling my cheap Chinese laser plotter:

For this project I will need a serial library. "libSerialPort" seems to be the standard library that is available (for Mint: Synaptic Package Manager - libserialport-dev) else I could use RS-232 library (https://www.teuniz.net/RS-232/). I rather like the RS-232 library.

Before using these serial port libraries you may need set the permissions for your ports using:

  •  sudo usermod -a -G dialout $USER

and then

  • login and logout

Grbl

"gCodeSender" talks to "Grbl" (https://github.com/grbl/grbl/wiki).


AlanX

Engrave.tap

A bigger version of fish6.nc

tap - 714.90 kB - 01/08/2019 at 00:02

Download

gCodeSender

Run in a terminal using ./gCodeSender

- 46.49 kB - 01/06/2019 at 14:09

Download

SerialTest.ino

Fake Grbl

x-arduino - 1.07 kB - 01/05/2019 at 06:46

Download

x-netcdf - 706.74 kB - 01/05/2019 at 04:16

Download

text/x-csrc - 26.46 kB - 01/05/2019 at 04:16

Download

View all 9 files

  • Grbl 0.7d

    agp.cooper01/07/2019 at 13:57 0 comments

    Grbl 0.7d

    My old laser plotter uses D12 for the laser control while Grbl 0.8 and higher use D11.

    D11 makes sense as it has PWM, but unless I hack the Controller hardware I have to stay with Grbl 0.7d.

    The old Laser plotter was never built to last. All the Perspex has cracked and broken (must be very cheap Perspex) and the ribbon cable glue has let go.

    Anyway I set the defaults for my laser plotter and yes it works. But recovery from an error or a state I had not thought of, needs a look at as the flags are not always properly set.

    The other problem is checking if the image will fit inside the plotting limits and setting plotting defaults. A popup configuration window may be helpful.

    ---

    Watching Grbl 0.7d burn its way through the code it is clear why my laser plotter was not used much and why I wrote the gCode Filter. Still it struggles to burn evenly even after filtering.

    Grbl 1.1f has made an effort to resolve this so it may be best to retire my old laser plotter and get a new one. Or at least rebuild the old one.

    AlanX 

  • The Real Grbl 1.1f

    agp.cooper01/05/2019 at 14:08 0 comments

    Grbl 1.1f

    Grbl has made some changes to the serial protocol. The "V" in front of version is gone and the speed is now 115200 baud.

    So a minor rework. Introduced a bug that cost a lot of time to find.

    Grbl has inhibited the reset on connection and prints a \r\n before the "Grbl " signature. You need to hit the reset  button to get Grbl to respond.

    Line terminations are \r\n (Windows) rather than \n (Linux) but Grbl tolerates \n.

    Still not working as I like, something for tomorrow.

    Uploading Grbl to a spare Nano

    First down load Grbl v1.1f from: https://github.com/gnea/grbl/releases

    I renamed the file to shorten it, to "grbl_v1_1f.hex".

    Although I have Arduino installed, I put it in /opt rather than among the system files.

    So I installed avrdude using:

    • sudo apt install avrdude

    To upload Grbl, open a terminal where the "hex" file is and type:

    • /usr/bin/avrdude -v -patmega328p -Uflash:w:grbl_v1_1f.hex:i -carduino -b 57600 -P /dev/ttyUSB0

    Obviously, my serial port is /dev/ttyUSB0 (yours may be something else).

    Strange Behaviour

    I was having problems communicating with Grbl.

    First problem with GUI programming is that different parts of the program can talk to the serial port. Make sure you are debugging the right place!

    Second, the end of line termination "\r\n" (i.e. Windows) did not work, even though Grbl is a "\r\n" device. The code has to use "\n". The "System" must be changing this on the way out?!

    Grbl uses a ^x as a soft-boot, I will have to add this to the initialisation code.

    Working

    Okay, it's taking to Grbl and although the Nano is not hooked up to the Laser machine, it is working is way though the file at its own pace:


    And:

    Note, the first "<< ", that was because there is a duplicate command, and the second "<< " was  a blank line at the end of the file. So all good.

    Need to look at initiation codes to make sure my units match.

    It Happens

    It was working! The image above proves it, but this afternoon it stopped.

    Any way I swapped out Serial code for the "Terminal" code as that was working.

    Turned off the Command Dialog while the print is active (could be messy).

    AlanX

  • Ready for Testing

    agp.cooper01/05/2019 at 04:14 0 comments

    Ready for Testing

    Pulled a couple of long days, but now the code appears to be working, just need to do some real testing.

    Here is the Control Panel:

    I have loaded a 49k lines gCode file (fish6.nc) and reduced it to 1k lines using the Input Tolerance slider (tolerance=0.1).

    If you "Show" the file you get:


    Next I turned on "Laser", which adds M3/M5 (Laser On/Off) codes depending on the Z value (on if less than zero otherwise off).

    Next I limited the feed speed to 100 units (mm/sec?).

    Then I Opened the Serial Port (/dev/ttyUSB0). You cannot print unless the port is open. When you open the port the controller (i.e. Arduino) is reset, and then you get the initialisation mesage "Grbl V".

    I then sent "G28", the Homing function to the controller via the Controller Command input box (as per the Control Panel image above). The file has G17 (metric) and G90 (absolute coordinates) is assumed.

    After that you can "Print" the file. The progress bar will grow and when done resets.

    You can pause printing by turning off the "Print" button.
    If you close the serial port the print will be cancelled.

    Here is the Control Panel after printing has been completed:

    You can see the M3/M4 Laser codes and the Feed Limit (=100) in action in he Controller Dialog window.

    There is probably some tweaking to be done with regard to how the buttons interact.

    For the Laser flag I block any M3/M5 codes in the file and insert M3/M5 for laser on/off.

    I also block any Z output if the Laser flag is set. This results in code like "M5G0", which seems strange but is legal (it changes mode from G1 to G0 which out moving):

    The same code without the Laser flag looks like this:

    One important issue with my gCode parser is that it only accepts the first code type (i.e. M, T, G, X, Y, Z, F and S) found on a line, any other of the same type is ignored. So if your code has something like "M3G1X10.0M5", then the "M5" will not be recognised (burn baby burn!). I think only hand written code will be like this!

    The Code is about 700-800 lines and needs a tidy up.

    If you have some horrible gCode (xyz) that you think will break my code, email me.


    AlanX

  • XForms' Form Designer

    agp.cooper12/29/2018 at 05:29 0 comments

    GUI Programming

    I generally prefer to code directly but why not try the Form Designer (fdesign).

    Where to Start? Perhaps page 93 of the documentation ("Part II - The Form Designer").

    Okay after two days it is pretty straight forward and easy to use.

    Here is my gCodeSender clone:


    Fonts

    That is changing the font type, size etc, does not seem to work. Te demo "fonts.c" does not work. It does not help that I Mint does not have the default font (i.e. helvetic-*-?, courier-*-?, times-*-?, charter-*-? and Symbol).

    Even then, if I try to install my own, they register but same result (i.e. font).

    After Another Two Days

    The serial port opens and closes pretty reliably. An unplug while the port is open hangs the port but the next port is provided upon "Reflesh" (i.e. "/dev/ttyUSB0" is lost but "/dev/ttyUSB1" pops up). The Arduino serial controller has the same problem.

    After lots of research I find the "hang" problem is not fixable. It is an issue with how the drivers work or coded.

    I added locks to the serial ports just in case of two program instances inter-react.     

    Still need to write the background serial port communications code. Looking to use the "idle callback procedure" for this. My stand alone serial test programs seem to be working properly.

    Wrote some code to sort out the line ending options (it pretends to be a Grbl controller). Yes, I get everything:

    • \n (linux)
    • \r (arduino!?)
    • \r\n (Windows)
    • \n\r (not so far!)
    • \0 (zero terminated string - not tested)

    The code looks like this:

    void setup() {
      // start serial port at 9600 bps and wait for port to open
      Serial.begin(9600);
      while (!Serial);
      
      // send a byte to establish contact until receiver responds
      establishContact();
    }
    
    void loop() {
      static char inByte='\0';         // incoming serial byte
      static char lastByte='\0';       // last incoming serial byte
    
      if (Serial.available()>0) {
        // get incoming byte:
        lastByte=inByte;
        inByte=Serial.read();
    
        if ((lastByte=='\r')&&(inByte=='\n')) {
           // Block on second byte of \r\n series
           inByte='\0';
        } else if ((lastByte=='\n')&&(inByte=='\r')) {
           // Block on second byte of \n\r series
           inByte='\0';
        } else if ((inByte=='\n')||(inByte=='\r')||(inByte=='\0')) {
           // Print if /r, /n, /r/n, /n/r or /0
           Serial.println("ok");    
        }
      }
    }
    
    void establishContact() {
      while (Serial.available()<=0) {
        Serial.println("Grbl V");   // send the initialisation string
        delay(1000);
      }
    }

    Form Designer

    The "Show" button calls "gCodeFilter" that pops up a display of the loaded file after filtering (i.e. Input Tolerance):

    A Terminal Program

    I found this Serial Terminal program (source: https://en.wikibooks.org/wiki/Serial_Programming/termios):

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <string.h> // needed for memset
    
    int main(int argc,char **argv) {
      struct termios tio;
      struct termios stdio;
      int tty_fd;
      char c='D';
    
      printf("Please start with %s /dev/ttyUSB0 (for example)\n",argv[0]);
    
      memset(&stdio,0,sizeof(stdio));
      stdio.c_iflag=0;
      stdio.c_oflag=0;
      stdio.c_cflag=0;
      stdio.c_lflag=0;
      stdio.c_cc[VMIN]=1;
      stdio.c_cc[VTIME]=0;
      tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
      tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
      fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);  // make the reads non-blocking
    
      memset(&tio,0,sizeof(tio));
      tio.c_iflag=0;
      tio.c_oflag=0;
      tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
      tio.c_lflag=0;
      tio.c_cc[VMIN]=1;
     tio.c_cc[VTIME]=...
    Read more »

  • X11 GUI Programming Research

    agp.cooper12/25/2018 at 01:57 0 comments

    Programming Directly in X11

    Okay I tried out the X11 demo programs.

    You certainly can write a procedure here if you need something special.

    Played around with loading some file images to screen.

    Yes they work but it is clear most people don't code GUIs down here!

    XCB

    Same here, was not much easier that X11.

    Xlib

    "Xlib" reminds me of GLUT (yeah I have done some coding here).

    Pretty easy to use but then I realised that all those procedures for text input, text windows, radio buttons etc. are missing. I never realised what a "Widget" was, and now I know! So I need an add-on library for the Widgets.

    Code:Blocks

    Code:Blocks has some GUI options so I thought I would have a look at them. Okay, there is wxSmith (a graphical Widget designer), and there is GTK+ and GLFLW, and no doubt others. I use Code:Blocks for programming in C but have no idea how the rest of it works.

    Time to have a bit of a look.

    GTK+

    It took quite a bit of work to compile my first demo program. I think the library was installed but the trick was to use the following options:

    • Other compiler options: `pkg-config --cflags gtk+-2.0`
    • Other linker options:   `pkg-config --libs gtk+-2.0`

    or

    • Other compiler options: `pkg-config --cflags gtk+-3.0`
    • Other linker options:   `pkg-config --libs gtk+-3.0`

    Depending on the library version you are using.

    It did not give me a warm fuzzy feeling, looking back I think it was the "documentation".

    No doubt there is a form designer but I did not find it.

    GLFLW

    Could not get it to compile, so I moved on.

    Time for some research

    I was wasting a lot of time now and not getting very far. The issue is that these libraries have steep learning curves and they not feel right for me (more power than what I need).

    The Wikipedia for X11 did not help much, but on the Wikipedia for Xlib I found the basic "widget" libraries: 

    So okay, I found Xlib and XCB, the client libraries.

    Found GTK+, so my options are Qt, FLTK and XForms (ignoring Xaw, Motif and OpenLook for the time being).

    A quick look at Qt said no for me (it is a monster) but I fell in love with XForms. Why, the easy to read and follow documentation, the (relatively readable code) and the simple form designer (fdesign).

    So (for the time being) my GUI library will be XForms.

    To compile an XForm GUI usually all you need is: "-lxforms" and occasionally "-lX11" (for low level functions).

    AlanX

View all 5 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates