probonopd / WirelessPrinting

Print wirelessly from Cura, PrusaSlicer or Slic3r to your 3D printer connected to an ESP8266 or ESP32 module
352 stars 65 forks source link

Work with printers without serial interface (USB Host Mode) #123

Open TheAssassin opened 5 years ago

TheAssassin commented 5 years ago

Some printers' boards, such as for instance the Creality Ender 2, don't have RX/TX GPIOs for serial communication, which means this project cannot be used with them. As these are mostly inexpensive printers, using OctoPrint with more expensive hardware is annoying due to the price.

The printers however mostly have USB sockets which can be used for serial communication. Therefore the question is: can an ESP board communicate via USB with those?

My hope is there's a USB-to-serial sort of adapter that provides a USB host and translates the USB stuff into raw serial again. The cheap UART adapters you can find online are functionally equivalent to the stuff in the printer board, they lack the host feature and cannot be used.

I know some Mega2560 based Arduino boards can provide a USB host feature and might do the translation, however they're quite bulky and also expensive. It might be cheaper to get something like an Orange Pi or so and try to run OctoPrint on there (UI won't run very well, I hope there will be a completely headless version in the future).

Perhaps there's a kind of USB host chip to do the translation which doesn't require a complex circuit that needs to be soldered on a PCB, as most people don't have access to the tools to realize that.

smartin015 commented 1 year ago

Neat that you're making a custom board! And yeah, I had to power mine externally as well as I don't think there's anything in the USB spec about supplying any amount of voltage from the non-host device. Did you try my original code on it to confirm the VCP stuff is working?

I think there could still be a pretty elegant solution that turns the S2 into a little bump on a "USB cable", something like USB A to power the S2 on one end and USB micro to connect to the printer on the other end. One could buy and hack apart a standard USB micro cable to put it inline as well.

dlyckelid commented 1 year ago

Neat that you're making a custom board! And yeah, I had to power mine externally as well as I don't think there's anything in the USB spec about supplying any amount of voltage from the non-host device. Did you try my original code on it to confirm the VCP stuff is working?

I think there could still be a pretty elegant solution that turns the S2 into a little bump on a "USB cable", something like USB A to power the S2 on one end and USB micro to connect to the printer on the other end. One could buy and hack apart a standard USB micro cable to put it inline as well.

No I havent got around to testing anything yet more than solving the issues I had with the PCB. I currently work on another project taking up all my time so will need to pause this until after May. I just cant start more projects right now. But yeah I have been thinking about the same thing but I am thinking of just having a type A usb for communication with printer and then a micro-usb for power. But it will be really small atleast.

smartin015 commented 1 year ago

Another update on my end: code is still quite hacked together, but I've managed to get

  1. USB connection established and printer discovered (via M115 command)
  2. Temperature auto-reporting parses successfully
  3. I can run a gcode file from SPIFFS and it succeeds on the printer

Video of all this working here: https://youtu.be/9qLVEFzK7UQ

@probonopd before I actually submit my draft PR and run the CI builds, I'd like your input on a few things:

  1. I extracted several of the string parsing functions from ESP8266WirelessPrintAsync.ino and converted them from Arduino String to instead use char*; they now live in lib/gcode/GCode.cpp. This was due to the string corruption errors I'd mentioned before. I've also created unit tests for them at test/test_gcode.cpp which can be run via pio test -e native -v. Assuming I can get this to build for all platformio envs, is this a reasonable change to you?
  2. Would you prefer the espidf components to be copied and checked into your repository (in the components/ dir, adds a few thousand lines of "code") or would you prefer I look into using a git subrepository setup or a quick script to fetch and unpack them?
  3. The espidf, arduino framework supports log_i, log_e etc. logging commands which have been very helpful for understanding what's going on. Would you prefer I include a couple of these to show the flow of gcode command send/ack and make them work for other boards, or strip them all out before I send the PR?
  4. As a heads up, I've been having issues with compile-time errors relating to 'Serial' not declared in this scope. I think this is some kind of config issue where the S2 only has Serial1 and Serial2, but no Serial var defined. I've been working around this by commenting out some of the Serial.println lines in the libs used by this project, and I haven't actually found a real fix yet. If you have any ideas, I'd appreciate it :)

In other news, I'm pausing development for around ~2wks as I've got some other projects that need attention. My PR should build and run just fine on an S2 mini however, so if anyone wants to pick it up and work on it they're more than welcome to keep going :)

probonopd commented 1 year ago

Unfortunately it does seem like atleast creality printers that I use does not provide a 5V source thru USB

Well, the printer is a device. The USB host needs to provide USB power. And in this case, this is the ESP. But possibly you can get the 5V somewhere from the printer mainboard.

probonopd commented 1 year ago

@smartin015 congratulations, I watched your video, this is awesome progress. :+1:

A real breaktrough.

Regarding your questions:

  1. Yes, let's do that. Please indicate clearly in the comments why it needs to be the way it is (or else you run the risk that next time I touch the code I inadvertently fall back to old behaviors)
  2. If we can have a separate espidf (sub)directory then I think it is easiest to copy those files (and their license file) there; I would not be surprised if sooner or later these functions would be integrated in a future version of the Arduino ESP32 core, at which time we should be able to delete this (sub)directly and change the include statements to use what the core provides
  3. I'd say leave the debugging statements in, if they don't cause issues while printing and uploading. Can the be enabled/disabled at compile time? (Bonus question, maybe for later: Would the debug statements make sense over telnet, too? At least in my case, I have no physical access to the ESPs which are built into my printers, so I use telnet to see what's going on.)
  4. How about using ifdefs to check whether it is an esp32-s2 and then use the corresponding SerialX?
smartin015 commented 1 year ago

Okay - I should have time this week to make some additional progress here. I'll

  1. proceed with C string parsing (including comments)
  2. relocate files to a new espidf directory. If using espidf with platformio requires them to be in specific locations, I can contribute a simple setup.sh to copy them to the appropriate locations so they're not cluttering the repo for non-idf users.
  3. I'll add instructions to the readme for how to enable/disable the logs at compile time, and make sure there's no printing issues.
  4. The errors happen in the supporting libraries that are downloaded by platformio, so I can't change them without maintaining a fork of each library. I'll keep searching for a solution.... I suspect it's related to modifying the console to output via UART.
probonopd commented 1 year ago

The errors happen in the supporting libraries that are downloaded by platformio, so I can't change them without maintaining a fork of each library. I'll keep searching for a solution.... I suspect it's related to modifying the console to output via UART.

Would it be possible to get the fixes into those libraries upstream? I think that would be the cleanest solution...

probonopd commented 2 weeks ago

https://github.com/luc-github/esp32-usb-serial is now available, which adds support for

to ESP32S3 and (untested) ESP32S2.

Maybe someone would like to integrate it here?

smartin015 commented 5 days ago

Hey @probonopd - long time no update from me. Apologies for leaving things half finished, life got busy.

I make no guarantees on additional work, but I did poke at the new arduino library you linked today. It builds with pio for esp32s2 (see https://github.com/smartin015/esp32-usb-serial-pio/) but I ended up submitting a PR to the original library as it was complaining about missing non-static members (see https://github.com/luc-github/esp32-usb-serial/pull/1).

Also had to specifically set the C++ version in platformio.ini as it was complaining about use of auto with C++11.

Haven't tested on a device yet; just wanted to leave some breadcrumbs in case another person wants a head start.

probonopd commented 4 days ago

Thanks for the update @smartin015. I don't think anyone besides you is currently working on this topic, so in case you ever get it to work with WirelessPrinting, we'd certainly appreciate a pull request.