Plus a few other machines running grblHAL in this showcase. The CBeam router is connected via Ethernet.
I'm actually up for a discussion of grblHAL about now, as it happens. Not for a machining center specifically, but for, let's say, a generic multi-axis machine (say a cartesian or SCARA robot) with a non-PC host (maybe RasPi) and likely custom sender, unless the standard sender has a headless operation and API, but I'm assuming, having read the grbl wiki fairly extensively, for grbl-type work that's unnecessary. Seems like grblHAL might be perfect for this type of "non-specific" system project, just like grbl itself is for anything with three arbitrary axes of motion and minimal IO. How exactly does the HAL work in grblHAL? It doesn't seem to be particularly similar to the "real" HAL in LinuxCNC, more of a higher-level "operating system parameters" over the grbl "kernel", compiled for specific boards and processors. Which certainly counts as an abstraction layer, just not so much for attaching arbitrary hardware and routing the signals accordingly. I see that it's possible to add M-codes for some digital IO, which may be sufficient for what I'm considering, how is this managed in the abstraction layer? It's not my own project, so I have no idea what the roadmap looks like, or even what the machine may end up looking like, but it does seem like 5 axes plus some moderate amount of IO would be plenty, whilst keeping things much simpler and cheaper/easier to replace than a full LinuxCNC install.
A starting point is here. It's more of a simplified overview. Here is the list of additional supported G and M codes over the standard Grbl set. You can see there are quite a few. Whether it is a "real" HAL is debatable. It completely abstracts away the underlying processor and peripheral details so in that sense it does exactly what it's name implies. Basically, it solves one of the problems with porting Grbl to new hardware - you don't need to change the motion control code and don't even need to understand how the core works. LinuxCNC capabilities were used as the model for grblHAL. It's a lot simpler than LinuxCNC which requires a pretty deep understanding of Linux. I've ported Unix Kernels to different processors and find LinuxCNC to be a bit daunting. I wonder how someone with less background handles it. Adding an M code is relatively straightforward. Essentially, the driver adds the functionality without having to modify the Grbl core. The wiki has a fair amount of information, especially a developer's reference including information about user defined M codes. To be fair, it is terse and a bit unpolished. Perhaps a more in-depth discussion would be better held in the issues section of the github page. The developer, Terje Io, is quite responsive and helpful. He is happy to talk you through creating one.
Yeah, I was browsing the wiki before/during posting, so I saw most of that as I referenced it in the post. It seems like more of a higher-spec, portable grbl for CNC vs being a truly flexible, extensible general machine control like LinuxCNC. Which is an excellent idea and totally makes sense in terms of getting "proper machining" to the hobbyist level, it looks perfect for that, but perhaps not quite what I'm looking for for this specific project, I don't think I'd quite understood the HAL aspect of it before today. If I do that mini extrusion 5-axis just for fun, I'd probably jump into it a bit more. I remember Sonny invited me to do some work on the grbl documentation and I never got to it (and it's really good now, so I guess someone did!), would be nice to actually put some work back into a FOSS project.
A grblHAL implementation has two or three parts: The core which handles g-code parsing, trajectory planning, step generation etc. Think of this as legacy grbl with all processor specific code ripped out (and a lot of stuff added, such as support for new M- and G-codes). The driver which is processor specific and handles hardware for setting output pins, interrupts, the serial stream (or other streams) etc. A number of optional plugins for extending functionality, many plugins requires driver support - some of this will be "hard" linked, some via the HAL. You can even add your own without changing a single line of code in the grblHAL master! --- The HAL is function pointer based, at startup a driver init function is called that sets up these to point to the functions that is required by the grblHAL core. The includes functions for setting stepper direction pins, pulsing the step pins, spindle control, coolant control, stream handling etc. My rationale for using function pointers and not "hard" linking everything together is that function pointers allows code to swapped in and out at run time or even "chained". An example is the SD-card pugin - this works by adding a few new $-commands, and redirects the input stream from the serial port to reading from the card instead by just temporarily swapping in the appropriate pointer when called for. The core has no idea where the input data is coming from and does need to know either - and there is no need for "if this then do that" statements in the core, it just calls the HAL to get a job done oblivious to how it is carried out. Adding new $-commands is done by subscribing to an event, in this case the unknown $-command event. If a command is recognized it is claimed and appropriate action is taken, if not it is passed on to the next subscriber (if any). A number of events are defined, allowing plugins and drivers too hook into the core to provide new functionality, such as additional $-commands and M-codes - again these are function pointer based. I hope this helps a bit in clarifying how the HAL works. Take a look at the code to get a better handle on it and ask when more specific details needs explaining.
Finally got some time to browse through this a little this morning. It does seem more abstract and extensible than I had thought, which is good and I may have some additional projects I could consider it for (especially with the hardware being so small) but it also seems self-limiting in terms of userbase in that you still have to understand, parse and edit a C file in order to add features and IO. From a consumer or end-user point of view, since I basically re-learn C every time I have to do something with it, and most of the time I'd generally like to avoid that, how feasible would you think it would be to have a more devolved, high-level data structure like LinuxCNC's HAL, where I don't need to learn C on Linux and recompile every time I want to change something, I just add a generic, fairly human-readable line to a text file that a lower-level function is probably already looking at, generates the necessary events, pointers, driver entries, and hooks it into the main thread. Seems like this could be replicable for all non-core functions, custom M codes, and all the rest of it. I don't know if it's a workable idea given the more limited power available in these processors, though it seems like it would be a startup function and not significant runtime overhead, but it would be nice from a user point of view to just "add stuff" rather than "edit code". Simple is better, if you're trying to spend time making stuff rather than fight with machines. Obviously this would be limited to the features and options you saw fit to add in releases- or whatever people edit the source code to allow- but generally there aren't too many varieties of add-ons for CNC machines. A couple of examples, if you're trying to imagine how that would work: 1) Let's say I'm mapping ballscrews, and obviously need to read a quadrature linear encoder, probably with some kind of I2C quadrature counter to eliminate CPU overhead, interpret its position, and write that to a file. Instead of adding in lots of lines of C in the encoder block that point here, there and everywhere, I'd want to do something in a separate file, where it's simply a line like, I dunno, ENC0 <ANALOG0> serial1 0x64 [AXIS0] and that initiates the encoder 0 object as a float considered by the G-code to be analog input 0, looking at whatever serial bus name the I2C bus is on the device and the device address, and since it's an encoder, maybe what axis it's tied to if it matters. Options there could also be [SPINDLE], [JOG], maybe locations like [INT7] for an interrupt-pin-7 pulse encoder, etc. The example would be read with an M66 E0 code just like the LinuxCNC standard that grbl follows (and I think you already have somewhat implemented, from what I saw). 2) Toolchanger. Let's say I have an X-Y rack picker (could be axes 4 and 5, could be an entirely different motion controller), a changer arm, and a rotating head. Plus the spindle drawbar. Instantiating a standard rack-style toolchanger with something super simple like TOOLS [10,10] for a 10x10 100-tool rack, or TOOLS [9,1] for a single 9-tool winerack and then other options for interfacing with it as necessary. I know that's a lot more work than it sounds like, because it would have to be interpreted and then injected to the main codebase, but it's one of those things where LinuxCNC is part of the way there with its HAL implementation but an inexpensive 5-axis grbl is mighty tempting if "regular people" can use it fairly straightforwardly. Also, random question, but given the more abstract nature of grblHAL, would it be possible to create a "cloud" of grbl cores, synchronized by their respective HALs and maybe a master RTC? I know this isn't possible in traditional grbl because of the way the buffers work, but the idea of just arbitrarily adding axes has always fascinated people.
Since grblHAL runs on a variety of processors with differing capabilities regarding peripherals and I/O pins this is fast getting complicated. The range of breakout boards that may be used makes it even more complicated... However, I believe there nevertheless is a some of similarity with the LinuxCNC HAL in that it is possible to wire stuff together in a simple manner. Of course the same level of freedom to pick and choose cannot be matched considering the constraints imposed by the supported microcontrollers and breakout boards. The growing number of grblHAL plugins is perhaps a testament to this. These typically hooks into the core and/or the driver and can be enabled by copying some files and editing a config file (example from the iMXRT1062 driver). Recompilation is required as there is no way to dynamically load modules, to avoid that all plugins has to be compiled in from the start and made configurable at run time. IMO this is neither practical nor desirable due to the constraints mentioned above. I have added configurable options to the core though, the latest beeing options for tool change on M6. This modifies HAL and core function pointers to provide its services. What is true for both the grblHAL and LinuxCNC HALs though is that there has to be driver code somewhere that provides access to the underlying hardware. If not provided out-of-the-box then writing code is unavoidable. I have added a HAL interface for M62-M68 commands - if supported by the driver/board then they become usable from gcode without changes to the core. Some of the plugins requires driver support for some of these and access the ports directly via the HAL. A plugin may even remove visibilty of ports from the core if it so wishes. These commands brings me to what is perhaps the biggest difference between grbl and LinuxCNC - there is no support for variables and subroutines in grbl, and IMO there will never be due to memory constraints. It is never, IMO, going to be simple as that - but then maybe someone my prove me wrong. The HAL has entry points for tool change so it is possible to add code for that without touching the core. A lot of work for sure, and for now I am pretty much the whole team behind grblHAL. If grblHAL gets a large(r) user base then this may change. Who knows, however I don't know how this could be implemented at this point. I have a FPGA sitting in a drawer that I want to explore for step generation etc. This could be used for syncing as well? But then I do not have time myself for following up all my crazy ideas...
Rob, you point out extremely valid issues but Grbl Classic has the same issue - you have to rebuild it. And often you have to make tradeoffs due to the contraints of the ATMega328p. Still, it is a huge success, despite that. Having dabbled with Linux CNC, I feel that the grblHAL approach is a lot simpler. Certainly there is a lot of flexibility and power to LinuxCNC because of that but, for even simple use cases, it is pretty daunting for even some one versed in Linux. Still, they all require getting down in the guts to make something to run. Terje has talked about a configurator approach - fill out a form and it spits back a binary for you to load. I like that idea a lot. I'd even donate space on a certain web site with a fairly obvious name if someone wants to help.