Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower cost per printer for network printing #13

Open
smartin015 opened this issue Mar 5, 2023 · 9 comments
Open

Lower cost per printer for network printing #13

smartin015 opened this issue Mar 5, 2023 · 9 comments

Comments

@smartin015
Copy link
Owner

smartin015 commented Mar 5, 2023

Raspberry pi's are expensive, and greatly increase the cost of a print farm if required per printer.

What if there was a low-cost esp32-based controller that could sub in for the raspi+CPQ plugin, that hooked up to the printer via USB and:

  1. Fetches IPFS files and streams them to the microSD embedded in the printer
  2. Starts the print and monitors its state
  3. Runs event scripts (perhaps pulled from a local website, or stored in EEPROM)

If it cost $4 instead of $150 per printer, that'd greatly lower the barrier to entry for prospective print farmers.

@smartin015 smartin015 changed the title Low-cost microcontroller for printing Lower cost per printer for network printing Mar 5, 2023
@smartin015
Copy link
Owner Author

Fleshing this out a bit more...

Hardware

  • 1-3 linux PCs, each hosting an octoprint server with CPQ and PeerPrint installed
  • A farm of printers, each with an ESP32 board attached via USB. The boards should probably be ethernet style to reduce wireless chatter and increase reliability. A custom board may be the best option in the end, as using a wired ESP32 as a USB host device doesn't seem to be very common currently.

Software

Note that gRPC is currently not supported on ESP32. Furthermore, logic for selecting useful work is currently in Python and runs via the CPQ plugin repository.

  • Use the IPFS client library for ESP32 to "cat" a file from the IPFS server straight onto the SD card of the printer.
  • Integrate the virtual COM Port USB host library to allow serial comms between an ESP32 and the 3D printer.
  • Expose an API endpoint from the CPQ plugin that proxies esp32 device requests to mutate the queue. This reuses the state machine in driver.py to control the printer, and effectively turns the ESP32 device into a "serial over ethernet" controller with a bit more printer-specific smarts.

Next Steps:

  1. Try out the IPFS client library and the VCP USB host library - if it can't fetch a file, write to SD, and then start the print, then the core idea is flawed.
  2. Buy a few ESP32 boards with ethernet and try to replicate (1)
  3. Convert "the driver" object in CPQ into a dictionary of drivers, keyed by the ID of the printer. Dynamically create/destroy these drivers as printers come online/offline.
  4. Separate out the on_update code in a way that allows OctoPrint or the ESP32s to trigger state transitions.
  5. Hack together some form of basic MDNS rendezvous that provisions the ESP32 peers with the URL of the IPFS server(s), the CPQ host(s), and any other relevant network details on boot.

@smartin015
Copy link
Owner Author

As an alternative, there's this proof of concept of USB/IP via ESP32-S2: https://github.com/chegewara/esp32-usbip-poc

This is basically hooking up all the printers via "ethernet USB" to a single PC however, which doesn't sound super great for reliability. I'd rather the core "host" logic be on the controllers themselves, and not on the OctoPrint server. Otherwise a restart of the OctoPrint server could take down all the active printers.

@smartin015
Copy link
Owner Author

Another direction to take this idea would be integration with an existing open source IOT project/framework. I'm a fan of Tasmota - however, there isn't a convenient guide for peripherals and it may add more initial complexity than is necessary for a proof of concept.

@smartin015
Copy link
Owner Author

smartin015 commented Apr 5, 2023

I managed to get the USB virtual com port example working, including redirecting console output to a different set of pins so at least printf debugging is possible. Attempts to use a higher-level (arduino framework) library failed, so it looks like we're going to be using the base esp-idf framework for this.

I also added a basic TCP server that allows opening a socket and sending data packets that are then repeated over USB serial, then write a simple script to connect and send some example GCODE commands.

@smartin015
Copy link
Owner Author

smartin015 commented Apr 6, 2023

Also discovered the new XIAO ESP32S3 Sense modules from seeed studio that incorporate an OV2640 camera. Definitely more expensive to install, but this could be really useful for spaghetti detection / initial QA of parts. All that's needed would be an additional HTTP endpoint for fetching a snapshot from the microcontroller.

@smartin015
Copy link
Owner Author

Thinking about behavior a bit, I imagine a setup like the following:

Config and connection flow

If not configured, self-host AP and allow configuration via simple HTTP interface. Configurable settings:

  • SSID
  • Password
  • Connection retries until self-host AP
  • Broadcast port
  • Broadcast period (seconds)
  • Idle time before broadcast

It may be useful to implement an auto-provision script that finds and connects to these self-hosted APs and provides specific configuration.

When configured, the device will connect to the wifi and broadcast its IP address on the given port for the PeerPrint server to discover. Broadcasting will cease when it receives a command. If it doesn't receive a command for a while, it'll begin broadcasting again.

Command flow

The PeerPrint server can send the following commands to an HTTP endpoint (followed by example responses):

{"command": "download", "cid": "<ipfs CID>", "src": "<ipfs server address>"} --> {"written": N, "status": "ok", "printer": "idle"}
{"command": "run_script", "script": "<gcode commands>"} --> {"status": "ok", "printer": "busy"}
{"command": "get_state"} --> {"status": "ok", "printer": "paused"}

download should use a modified version of https://github.com/exmgr/ipfs-client-esp32 to fetch the file from src and write it via GCODE to the SD on the printer.

run_script should execute the gcode directly on the printer. get_state should return current state of the printer.

@probonopd
Copy link

probonopd commented Apr 16, 2023

Check out https://github.com/probonopd/WirelessPrinting

It emulates enough of the OctoPrint API to let e.g., PrusaSlicer discover it via Zeroconf and print to it like if it was an OctoPrint instance. I've been using it for years to do all my 3D printing.

fetch the file from src and write it via GCODE to the SD on the printer.

I have never found a way to do this (fast).
Instead, WirelessPrinting uses a microSD card connected to the ESP and stores the GCODE there.

What we didn't have so far is USB host mode, but it seems like you have figured that part out:
probonopd/WirelessPrinting#123

@smartin015
Copy link
Owner Author

smartin015 commented Apr 16, 2023

Check out https://github.com/probonopd/WirelessPrinting

It emulates enough of the OctoPrint API to let e.g., PrusaSlicer discover it via Zeroconf and print to it like if it was an OctoPrint instance. I've been using it for years to do all my 3D printing.

Very cool - using a "standard" API certainly opens up a lot of possibilities.

fetch the file from src and write it via GCODE to the SD on the printer.

I have never found a way to do this (fast). Instead, WirelessPrinting uses a microSD card connected to the ESP and stores the GCODE there.

Gotcha. I was hoping to not require a microSD slot on the board as that bumps up the price. Did you try GCODE based SD writing by any chance? What was the performance like for that?

What we didn't have so far is USB host mode, but it seems like you have figured that part out: probonopd/WirelessPrinting#123

Yup - I mostly just mashed together the existing esp-idf examples into something barely functional. I see your project uses the Arduino framework... AFAIK there's not a decent port to an arduino lib yet from the IDF examples. I tried a couple, none of them really seemed well supported.

In any case, I see some collaboration potential here :)

@probonopd
Copy link

Did you try GCODE based SD writing by any chance? What was the performance like for that?

I didn't really try it as I was told it would be slooow. Maybe worth a try nevertheless.

In any case, I see some collaboration potential here :)

Cool 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants