MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.16k stars 19.21k forks source link

[Announcement] Preview of Marlin enhancement we will demonstrate at Midwest RepRap Festival #10008

Closed marcio-ao closed 5 years ago

marcio-ao commented 6 years ago

Hi everyone,

At the Midwest RepRap Festival this year, we are going to be showing off a cool Marlin enhancement that we have been working on: a color LCD touch interface for Marlin based on the EVE controller chips from FTDI.

Watch the video (click picture for video)

We also will bring our first prototypes for display boards based on that chip. As usual all of our work is open source and under the GPLv3 license. Our boards will use the same connector and ribbon cable as the RepRap Discount display and thus is an easy retrofit. It's also very light on SPI traffic, so should be usable on all printer configurations.

While our boards are not yet in production, the code in our "devel" branch of Marlin can drive the LCD from Haoyu Electronics . Basic printer operations are already controllable from the touch interface. Our code currently supports both landscape and portrait orientations, at 800x480 or 480x272 resolution.

We are also working on open-source hardware and software for SD card support and USB pen drive support which will work in conjunction with the touch panel.

If you will be attending the 2018 MidWest RepRap Festival, come find us to see these prototypes in action!

thinkyhead commented 6 years ago

I plan to attend, so I guess I should get my travel plans in order! I look forward to seeing you, @houseofbugs, and various other movers and shakers on the scene.

marcio-ao commented 6 years ago

@thinkyhead : Looking forward to meeting you!

yellobello commented 6 years ago

Hi, will it support marlin natively and give access to the marlin menu structure or is it a gcode-type panel that talks to marlin in gcode, like most of the other color toch lcds do?

marcio-ao commented 6 years ago

@yellobello: It is a native interface, but it does not share the menu structure with the ultralcd code, so not all features are present (unless someone adds those features).

I have tried to consolidate the bits and pieces that actually talk to Marlin in a class called Marlin_LCD_API. My thinking would be that it would be nice to have a common interface so that different UI implementations did not have to duplicate that code. But this is just a suggestion at this point and I don't know what would be the best way to provide an extensible LCD API.

marcio-ao commented 6 years ago

To be honest, I was not even aware that there were touch interfaces that operated at the GCODE level. I wonder whether that is a better way to do it? I only made a native interface because I was basing my work on the ultralcd code.

amoose136 commented 6 years ago

I think what @yellobello is talking about is touch screen interfaces like octoprint where a secondary controller handles all graphical computation so as to not interfere with motion control but then communicates with the printer main board via gcode commands sent over serial. In my experience this approach works well but it has the side effect of introducing lengthy command queues for buffering reasons. Eg: If I press pause on octoprint mid print it will immediately send the pause command but it goes to the back of the queue so another 10 or so moves happen before the print actually pauses unlike with pausing from the printer front panel which is almost immediate.

Roxy-3D commented 6 years ago

We do need some deep thinking on the LCD code. The LCD code served a purpose, and started growing. LCD Panels became cheaper and more prevalent and more and more functionality was pushed into them (from a Marlin perspective). But none of it was really planned with a sustainable growth path.

We need to preform surgery and cut some of the tentacles that have grown (in both directions) between the main firmware and the LCD functionality.

And that really has nothing to do with Touch Displays (which are cool!!!), but the people reading this thread are the right ones to make suggestions and contribute thoughts on how to accomplish that.

thinkyhead commented 6 years ago

suggestions and contribute thoughts

One good way to remove dependencies between units is to use a general Broadcaster-Listener system. Objects that are interested in messages simply register as Listeners for those messages. Then any object with the right inheritance, or at least a reference to the Notifier, can act as a Broadcaster. This can be extended with an event queue and dispatcher, as commonly used for application APIs, sending events to listeners in a hierarchy who can choose to handle them and/or let them propagate to their parent controller. This would require various classes in Marlin to be re-architected to inherit from a Listener class and operate modelessly rather than sitting in loops calling idle(), but it would be more elegant.

Roxy-3D commented 6 years ago

suggestions and contribute thoughts

One good way to remove dependencies between units is to use a general Broadcaster-Listener system.

Yes... And I know this is a religious topic... But what I'm hearing is we need to use message queues and semaphores to control access to critical resources like the LCD Panel and Encoder Wheel. It may not take a big re-write of the classes. It may be possible to do that with some careful surgery to isolate various 'tasks'.

thinkyhead commented 6 years ago

Basically, yes. A "listener" is really just a function pointer. The dispatcher just has a list of these functions and in the simplest implementation just calls all of them, passing the "message" which may be as simple as a single byte. If the listener isn't interested in the message it can just ignore it. To reduce the number of calls, listeners can specify a bit pattern for the type of message they want and the dispatcher can only call those listeners that care about the type of message being broadcast. To pass data, you just send a struct* to the listener, and it can interpret the data according to what it expects.

marcio-ao commented 6 years ago

I like where this discussion is going. When writing my own touch LCD code, I noticed that that "ultralcd.cpp" called a lot of Marlin internals. I am by no means suggesting this is the right way of doing it, but here is how I managed to separate out the Marlin bits and pieces so it wasn't all over in my color LCD code:

https://code.alephobjects.com/diffusion/MARLIN/browse/devel/Marlin/AO_UI_Marlin_LCD_API.h

This sort of gives an idea of the functionality which needs to be exposed to LCD code.

marcio-ao commented 6 years ago

These functions poll the state from Marlin, so then I needed to implement an idle function that would cause the LCD code to call functions in the Marlin_LCD_API to pull information.

Using a "listener" approach would turn things around, where Marlin would be calling code in the LCD module when things changed. Although both can be made to work, I think the idle() and polling approach has an advantage: for a lot of LCDs, the refresh code works by painting the entire screen at once. If you have an idle() function, that function can simply request the pertinent bits of information needed to draw by using Marlin API calls to poll the info. If the API were instead a message listener approach, then the LCD module would end up shadowing the information in local variables until it was ready to do refresh, which mean way more memory use.

davidelang commented 6 years ago

On Tue, 1 May 2018, Marcio Teixeira wrote:

If the API were instead a listener approach, then the LCD module would end up shadowing the information in local variables until it was ready to do refresh, which mean way more memory use.

I think which is better depends on how frequently the data changes and how frequently the display updates.

If you are displaying data that doesn't change much, and are updating the display frequently, polling for it every time you go to update the display wastes a lot of time.

If you have data that changes a lot, and a display that updates infrequently, you spend time pushing data to the display, where it sits in variables until it's replaced by the next push.

The push has the advantage that while you are using the value for other reasons, pushing it to a new place is pretty cheap (even if you have to filter to see if the destination actually cares about the data)

It also sets you up well to supporting off-board devices (serial or network) where the overhead of a query is much higher.

ModMike commented 5 years ago

I just took a look and wow. That is a WAY BETTER solution!

chrisqwertz commented 4 years ago

Recently received bunch of Riverdi LCDs in sizes from 2.83" to 7", many with capacitive touch, and with FT80X/FT81X/BT81X eg. EVE1/2/3 driver boards for evalution. If there is demand, I could verify / add a few display configurations

github-actions[bot] commented 4 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.