Using multiple 3D Printers with a single Raspberry Pi and OctoPrint
ChinookTx

Last updated on June 23rd, 2017 at 09:15 am

This post will describe how I have configured my RaspberryPi (v3) to run multiple instances of OctoPrint and use multiple 3D Printers with it.  The information here is based heavily on a post by Pat Ragan on his blog.

The commands listed here worked on a stock install of OctoPi 0.13.  If you have a different version, you might want to modify the files manually.  If you cut and paste the commands, makes sure you select the lines all the way to the end, they don’t get fully displayed!

With that said, let’s get started

Setting up a second instance of OctoPrint

The first thing you’ll want to do is ssh to your RaspberryPi and sudo as root:

[code language="bash"]
sudo -s
[/code]

In order to start the 2nd instance of OctoPrint, a startup script needs to be created in /etc/init.d.  It is mostly a copy of the existing one, with a few things modified to ensure there is no conflicts between the two.  Mainly, all instances of “octoprint” are replaced by “octoprint2” and instances of “Octoprint” are replaced by “Octoprint2“.  The last part of the command restores one of the statements that shouldn’t have been changed since the same binary is used for both OctoPrint instances.

[code]
cd /etc/init.d
sed s/octoprint/octoprint2/ < octoprint | sed s/Octoprint/Octoprint2/ | sed s/bin\\/octoprint2/bin\\/octoprint/ > octoprint2
chmod 755 octoprint2
[/code]

Next, the startup script needs to read its settings from a configuration file, stored in /etc/default. The second instance will use port 5001 (first instance uses 5000). It will also bind to “all” network interfaces and not just localhost. This will allow bypassing haproxy if you don’t have a DNS server or don’t want to mess with DNS settings.  The last part of the command also ensures a different directory is used by OctoPrint for its runtime and to save its settings.  Without that, both instances will fight and overwrite each other’s data.

[code]
cd /etc/default
sed s/PORT=5000/PORT=5001/ < octoprint | sed s/HOST=127.0.0.1/HOST=0.0.0.0/ | sed s/\$PORT/\$PORT\ --basedir\ \\/home\\/pi\\/.octoprint2/ > octoprint2
[/code]

Once everything is configured, the 2nd instance is made to automatically start up at boot time.

[code language="bash"]
update-rc.d octoprint2 defaults
[/code]

And finally, it is manually started.

[code language="bash"]
service octoprint2 start
[/code]

That’s it, your second instance should be accessible at the same ip address as your first one, but on port 5001:

[code language="bash" autolinks="false"]
http://yourIpAddress:5001
[/code]

Configuring udev to map devices to a user friendly name

The default names for the attached USB printers will be something like /dev/ttyACM0/dev/ttyACM1, etc.  One of the problems is that depending of the order the devices are plugged in, or which port they are in, they might come up with a different name after a reboot.  In order to avoid confusion, it is possible to map a more meaningful name to a device.  For example, you could have /dev/prusa and /dev/printrbot, etc.  This is done through udev configuration.  You first need to find a couple of values that uniquely identify your printer, and tell udev what to do when it sees those.

To simplify things, make sure you have a printer plugged in when you do the following.

[code language="bash"]
udevadm info -q all -n /dev/ttyACM0 --attribute-walk
[/code]

This will spit out a lot of information.  You are looking for the section that has an entry with a serial number.  In my case there were 2 sections with serial numbers.  Only one is valid.

[code language="bash"]
ATTRS{serial}=="some serial number"
[/code]

You are looking the the serial number that does not match the one that is listed in the section headers.  For example, if your sections begin with:

[code]
looking at parent device '/devices/platform/soc/3f980000.usb/...'
[/code]

You want to find the section that has a serial number entry that is NOT 3f980000.usb

Once you have the right section, you need to extract the following values from it:

[code language="bash"]
ATTRS{idVendor}=="someVendorId"
ATTRS{idProduct}=="somProductId"
ATTRS{serial}=="someSerialNumber"
[/code]

Finally, you can create the rule for udev to use when it sees the connected device.

[code language="bash"]
cd /etc/udev/rules.d
[/code]

create a file called 99-usb.rules, which will contain a line like this:

[code language="bash"]
SUBSYSTEM=="tty", ATTRS{idVendor}=="someVendorId", ATTRS{idProduct}=="someProductId", ATTRS{serial}=="someSerialNumber", SYMLINK+="theNameOfTheDevice"
[/code]

This will create a symbolic link called /dev/theNameOfTheDevice that points to the usb device, regardless of which /dev/ttyACM* it gets assigned.  Repeat with other printers to get their own values.

At this point a reboot would probably not hurt so go ahead and issue the reboot command:

[code language="bash"]
reboot
[/code]

Upon reboot, when connecting your printers, you should see a symbolic link created in /dev for them.  For example:

[code language="bash"]
lrwxrwxrwx 1 root root 7 Dec 10 02:24 printrbot -> ttyACM1
lrwxrwxrwx 1 root root 7 Dec 10 02:24 prusai3 -> ttyACM0
[/code]

There is one last step required in order to see the devices in the OctoPrint web interface.  In the Settings pane, under Serial Connection, the device name will need to be added to the box Additional Serial Ports.  In our example, you would add:

[code language="bash"]
/dev/theNameOfTheDevice
[/code]

Save the settings, refresh the main page and the device should be available in the Serial Port drop down!

Continue on to the next post, where I cover the configuration of haproxy if you’d rather use DNS entries to access the instances without having to specify the port.

Join in Comment below...