Limited items in stock
View Purchasing OptionsHi, beloved X1Plus supporters!
I’m back from Supercon, and I’ve mostly shaken off the "con crud". I just looked at the crowdfunding page, and I’m feeling very honored that so many of you have decided to buy X1Plus Expander — this has been an incredible success so far, much beyond the minimum I needed to make this possible, and so I’m looking forward to getting to use some of the economies of scale to put together nicer packaging and prettier plastics. If you haven’t ordered yet, there’s still time to order your X1Plus Expander! And definitely make sure to watch the video on the top of the page if you haven’t, yet. That was more hours of filming than I care to admit, and it was really hard work getting Peanut (the cat) to sit still long enough to get a nice shot of her in frame!
In the mean time, over the past week, I’ve been hard at work documenting the X1Plus Actions subsystem so that we can get some units in the hands of YouTube creators. It’s still very early days, but I wanted to give you all a taste of what you’ll be able to do with X1Plus Actions. So without further ado, let’s take a deep dive into…
A part of X1Plus Expander, there are a wealth of ways to interface with the outside world. X1Plus Expander can talk to I2C devices, to camera shutters, and to buttons that you can press — and if that doesn’t do it, it has 3.3V GPIOs for you to attach to any external device that you can think of. But as we know about 3D printers, having theoretical hardware support is useless unless there’s software that can meaningfully drive it!
In X1Plus, the software counterpart to all of this hardware flexibility is a new system we’ve built called X1Plus Actions. X1Plus Actions let you write small chunks of JSON to call up predefined commands in the X1Plus system, and to specify their behavior however you need. For instance, you can write a simple Action to wait five seconds, then send a G-code command to heat up the nozzle:
[ { "sleep": 5 }, { "gcode": "M109 S200" } ]
Or perhaps you’d like to write an action to beep the buzzer (which we do by pulsing all GPIOs that are assigned to the "buzzer" function for half a second):
{ "gpio": { "action": "pulse", "duration": 0.5, "gpio": { "function": "buzzer" } } }
In the initial X1Plus Expander firmware release, we’ll have support for the GPIO, G-code, and delay Actions listed above, as well as a few more — but there’s work in progress to add plugins to the X1Plus daemon, so you’ll be able to develop your own, as well!
The beauty of X1Plus Actions is that they are a unified system that appears in multiple places around the system. For developers, you can run X1Plus Actions directly at the command line using the x1plus action
command. You can also embed X1Plus Actions directly into G-code, so that you can design Actions that run while you print. And you can configure X1Plus to respond to external GPIOs by running Actions!
Actions are designed to be usable either as a development platform for advanced behaviors, or just as simple recipes that you can paste into your prints and projects. Let’s take a look at a few examples.
One of the use cases we designed Actions for is to control an external camera’s shutter release to take time lapses while you’re printing. The general idea of doing this is simple: at certain points during your print’s G-code, you’ll want to trigger an Action to fire the shutter. The JSON for this is relatively straightforward: it triggers the shutter, waits a second, and then tells the printer to continue printing. It looks like this:
[
{ "gpio": { "action": "pulse", "duration": 0.5, "gpio": { "function": "shutter" } } },
{ "delay": 1.0 },
{ "gcode": "M400 W0" }
]
To trigger it from G-code, we use the special ;x1plus define
syntax, and trigger it with a special M976
G-code command. If you want to trigger it on every layer change, you can put it in the "Layer change G-code" box in your slicer, right under the M971 S11 C10 O0
line that’s already there (that’s the line that triggers the built-in time lapse in the printer). The G-code to run this look like this:
M400 ; wait for printer to stop moving
; define the command for X1Plus Actions to use
;x1plus define 100 [{"gpio": {"action": "pulse", "duration": 0.5, "gpio": { "function": "shutter" }}}, {"delay": 1.0}, {"gcode": "M400 W0"}]
M976 S99 P100 ; trigger the action!
M400 W1 ; pause the G-code until the action completes and sends the M400 W0
(Note that some slicers have trouble adding JSON directly into G-code. To work around this, we have a special "compiled Actions" mode that you may need to use — you can read about it here, if you’re curious. We hope to have better slicer integration by the time we get boards out!)
The nice thing about this is that you can customize it to your heart’s content, if you like — or, if you just want to take a time lapse without knowing anything about X1Plus Actions, you can copy-and-paste the G-code and go!
X1Plus Expander’s Andon Module has two buttons on the top. Wouldn’t it be nice if you could map those buttons to various behaviors in the printer? As it turns out, we designed Actions to be able to support this use case, also. As part of the GPIO mechanism that we built to go with X1Plus Expander, we added a setting to map GPIO events directly to Actions. These are also defined in JSON, using an X1Plus Settings key named gpio.actions
. For example, if you wanted to map the left button on an Andon Module to raise the bed slightly, and the right button to lower the bed slightly, you might have the following configuration for gpio.actions
:
[
{
"gpio": { "board_type": "X1P-005", "pin": 6 },
"event": "short_press",
"action": { "gcode": "G91\nG0 Z2.5" }
},
{
"gpio": { "board_type": "X1P-005", "pin": 7 },
"event": "short_press",
"action": { "gcode": "G91\nG0 Z-2.5" }
}
]
The action
in each of these gpio.actions
is just an X1Plus Action like any other. (If you wanted the world’s most complicated remote shutter release for your camera, you could use the Action that we created above for a shutter release, and map that to a button press on your Andon Module!) The new functionality here is that you can map the behavior of a GPIO to an Action; you specify which GPIO you want to map using the gpio
key (which, in a lovely symmetry, has the same format as the gpio
key of a gpio
-type Action!).
There are all sorts of things you might want to do with GPIO controls. You might want to send a sequence of G-code to preheat the bed, for instance, if you’re planning to print some Nylon. Or, if you have external peripherals attached by GPIOs, you might add a remote mechanism to pause and unpause prints!
Just like G-code Actions, GPIO Actions are very flexible and powerful. But they’re designed to be consistent between printers, no matter how you have yours set up, which means that you can share GPIO Actions as "recipes" and just get started right away!
This is just a taste of where we’re going with Actions. As you can probably tell, it sure is early with all of this implementation, and it is not without its warts! Writing JSON by hand is sort of clunky, and configuration can be a challenge right now. To take the next step in making Actions more usable, we want to know what you want to use them for! So my question to you is: what would you want to use Actions for in your setup? Are there certain types of Actions we should implement? What might you want to trigger from a print, what might you want to trigger from a button press, and what might you want to trigger from an external peripheral? And how would you want to configure it? If you have thoughts on any of these, I definitely want to hear it — or even if you don’t plan to use Actions, I always want to hear about how you’re going to use your Expander — so feel free to send me e-mail whenever you like!
There’s just under a month left on the campaign, so there’s time left to order yours if you haven’t already. Next week, I’m hoping to have some time lapse footage for you. I’m super stoked with how it’s turned out so far!
Talk soon —
joshua