OctoPi not reading SD card or print progress from Ender 3 (SOLVED)

Hi All,

I can confirm that it works in an Ender 3 Pro purchased at the end of August.

Thanks for your contributions

I used Ender-3s printer, I cant get sd card file from octoprint. I just follwoed b-morgan steps , but I still cant get anything . So I Unmark "Enable automatic firmware detection" and mark "Always assume SD card is present- Repetier" in Octroprint Settings / Firmware & Protocol.It works well.

1 Like

plug-in works like a charm! thank you!

I guess what the plugin does is to intercept every line received by the printer. If it contains "SD" then it replaces "SD" with "TF". This approach has the drawback that a function is invoked (the callback itself) which itself does further more calls (basically find&replace).

Here I provide an alternate solution by directly patching the file that handles Octoprint's communication with the printer (comm.py) which from my point of view is more performant then to hook in a plugin. I have octoprint installed via pip in my home folder. Alternatively you can change COMM_FILE to whatever location fits for your installation.

LINE_WITH_SD_IN_IT="elif 'SD card ok' in line and not self._sdAvailable"

if [ "$LINE_IN_COMM_FILE" != "" ]
  echo "It seems the file $COMM_FILE requires patching. To continue hit enter"
  echo "Please restart octoprint"
  echo "No need to patch $COMM_FILE"

I placed this file in my home directory and made it executable (chmod +x). It has to be executed every time an update of octoprint overwrites the comm.py file.

I had the same issue and read the whole thread. It's disappointing that no one found the correct answer in this thread.

No plugin or changes to files are needed .. @NRom posted the correct solution twice:

1 Like

@Scott_Westberg b-morgan's #6 post may have been helpful previously but is no longer the best method, @NRom has posts below on how to fix this through the GUI, can you please change the solution to his post?

Why? If the solution he choosed works for him. The solution of NRom is another solution.

All I read here are workarounds, no solutions. I also tried the "Always assume SD card is present- Repetier" which resulted in other errors - I was no longer able to connect to my printer.

The problem is located in the Ender3's firmware. A solution would be to patch that - but that's out of scope. Another cleaner solution would be not to catch fixed strings in comm.py. Instead use translations and provide a translation file for each printer so that the whole parsing becomes independent of the strings themselves.

That's not how communication protocols work.

1 Like

I am talking about implementation not the protocol.
By the way: where is this protocol being specified? I cannot find it.
Protocol means there is a contract how the data is communicated between peers. So if there is no such official specification, than you cannot rely that the messages received by the printers are all the same. So the parser should be more flexible - which could be done by sourcing according translations instead hardcoding fixed strings.

You really do not want to get me started on this discussion, especially not right now. Trust me.

Take a look here and here and watch this.

The only specification we have is a wiki everyone can edit, that's a nightmare for host software development, I'm already bending over backwards everywhere but at some point it just stops working catering to firmware forks doing whatever the fsck they want and a line has to be drawn to not make everything a completely unmaintainable mess for good.

Printer vendors and firmware devs have a responsibility too, yet for some reason I am/OctoPrint is supposed to shoulder all the work and maintenance overhead to keep things interoperable, and frankly, that's annoying AF. Your suggestion would make that even worse. And still it is actually the direction that the comm layer rewrite is taking, though not with a translation file, because just the communication strings aren't the only thing that constantly gets fscked around with by vendors who have no bloody idea what they are doing and breaking left and right.

... sorry. Rant over. Really a bloody sour topic for me that's causing me actual nightmares, literally.

Ah, now I see!
@foosel I am so sorry I did not intend to offend you. You did a great job with developing and sharing OctoPrint with us - so many people are greatful!
I am python & firmware dev too and I totally understand your frustration. I just stumbled upon this very special issue with my Ender 3, read the source in comm.py and asked myself how the parser could be extended so that the strings don't need to be hardcoded. I had no evil thoughts. Ich will kein Fass aufmachen.

Not hardcoded strings would mean that you don't have to reship the whole parser when some vendor f**ed up with a message. Instead just a single line in - what I call translation file - needs to be changed.
Following a very simplified example. I know this uses a dict but this can be tuned to anything userfriendly simple editable.

# tranlsation.py
Translation = collections.namedtuple('Translation', 'prusai3 ender3') # any other printer may go here
translations = dict(
    SD_CARD_INIT_OK_RESPONSE=Translation(r'^SD card ok$', r'^TF card ok$'),

def _(key, printer) -> str:
    return getattr(translations[key], printer)

# in comm.py
##~~ SD Card handling
    # assume the printer var holds the printer name, e.g. 'ender3'
    elif _('SD_CARD_INIT_OK_RESPONSE', printer) in line and not self._sdAvailable:
        self._sdAvailable = True

So if the Ender 3 again f**s up from "TF card ok" to "microSD card Okay" then one would only have to change the line in translations.py.

No worries. It's just really a bit of a stressful time for me right now (sponsor situation, RC, some Py3 compat stuff blowing up, on top of everything else). I'm sorry for blowing up.

I understand the idea behind your suggestion. The problem is it wouldn't avoid shipping, I really don't want to start reading stuff like that from a server on startup :wink:

Current approach for the new comm layer are (plugin extendable) protocol layers that hold the strings and other stuff that cannot be easily fit into a text file in so called "flavors" which then get selected either automatically based on detection or by the user. The idea would be in the future to then allow someone to write a plugin that adds a new "Ender 3" flavor to the mix, maybe also with detection based on M115 responses, and publish that.

You can take a look at the current implementation here: https://github.com/foosel/OctoPrint/tree/dev/commRefactoringNG/src/octoprint/comm/protocol/reprap/flavors


The problem is it wouldn't avoid shipping

That is totally correct! But: for people like me or other users in this thread it would be easier to "fix" such issues.

Current approach for the new comm layer are (plugin extendable) protocol layers that hold the strings and other stuff ...

Ah okay that sounds to me there is some heavy refactoring going on? To use plugins that hold everything that is required to handle communication with different flavors (printers?) is something I totally agree with.

You can take a look at the current implementation here

You really want me to do that? I am a very hard coder reviewer :smiley:

Yeah, that refactoring has been going on for a long time actually. I originally wanted to get it into 1.4.0, but that caused issues with the timeline due to the pending py2 EOL. It's still in the process of being worked on (though on hold while I take care of 1.4.0rc stuff - once again, which is another source of frustration). With that in mind, knock yourself out, if you want to look over it I'd be thankful, as long as you keep in mind that it's not final :wink: The whole octoprint.comm tree is actually new.

Continuing the discussion from OctoPi not reading SD card or print progress from Ender 3 (SOLVED):

Sorry to rake this up again but I can't get this to work, wonder if you might have any pointers. Quite ok with linux so I'm at a loss as to what is wrong.

Octoprint 1.3.12

I've created the file in the ~/.octoprint/plugins directory from a cut/paste of the code above, into mcedit - unix editor. File is named 'convert_TF_SD.py' and python has built a corres .pyc file beside it so I'm assuming it's being found OK. I note it's been variously named 'convert..' and 'Convert..' in the discussions above. The file is chmod 777.

Rebooted the pi but still the 'Upload to SD' button is disabled. M21 still says 'TF card OK'. Plugin doesn't appear in the Plugins list.

I don't really need the functionality but would be nice to get it working and know why.

I have the same issue, same version and I used the file in the ZIP from an earlier reply. I even tried the suggestion to disable the options under Firmware, but that still makes no difference.

Both M20 and M21 return valid results as far I can tell:

Send: M20
Recv: Begin file list
Recv: CAT-35~1.GCO 34432620
Recv: DOG-25~1.GCO 12449184
Recv: PIG-4H~1.GCO 19126652
Recv: ENDER3~1.GCO 151321
Recv: End file list
Recv: ok
Send: M21
Recv: echo:TF card ok
Recv: Init power off infomation.
Recv: size:
Recv: 585
Recv: init valid:
Recv: 0
Recv: 0
Recv: ok

It worked for me if I turned on "Always assume SD card is present- Repetier" as discussed but in the end I made the changes in the comm.py file as per @siochs suggestion. Worked straight away too and I'm OK editing files in linux.

I don't really need to use the SD from octoprint - but it should be working so I patched it!!

1 Like

Thank-you, I changed the same file and it's detected now.

Worked like a charm for me! I will try to recomplile Marlin "any day" and that will hopefully resolve it in a cleaner way for me.

The easy and quite ugly way of installing the plugin is to just connect to octopi via SSH (or login as the effective octoprint user on your machine) copy this snippet (which is just @b-morgan s code) and paste it straight into the terminal:

cat > /home/pi/.octoprint/plugins/convert_TF_SD.py << EOF
# coding=utf-8
from __future__ import absolute_import

def convert_TF_SD(comm, line, *args, **kwargs):
    if "TF" not in line:
        return line
    goodline = line.replace("TF","SD")
    return goodline

__plugin_name__ = "Convert TF to SD"
__plugin_version__ = "1.0.0"
__plugin_description__ = "Convert TF to SD in printer responses"
__plugin_hooks__ = {
    "octoprint.comm.protocol.gcode.received": convert_TF_SD

sudo service octoprint restart
1 Like