Closed NightFalcon650 closed 6 years ago
Due to the communication delays, it's close to impossible, to keep the steppers on the second board/processor in sync. All steppers connected to one single board and the rest of the devices to an other could be possible. That would require different boards, we do not have. Maybe an idea for Marlin 3.0 - if we have the boars then.
That would be nice, having the main board with steppers for the axis and feeders. And a second board for lcd, heaters, vents etc. What type of boards do you mean?
the type that prob are not made yet :-D
While I think that port expansion would be great, cobbling together a dual-arduino monstrosity is probably not the best way to go about doing this. I think an I2C or SPI based port expander would be a much more elegant solution and may be quick enough to keep stepper synchronization. There may be issues with pins that need interrupt routines, such as endstops, and PWM may take some work.
I'm working on exactly this project now, and have just today extended the EXPERIMENTAL_I2C_BUS
feature to support slave connections between two instances of Marlin, or to allow a single Marlin instance to act as a slave on the bus. The second RAMPS is just controlling the Z axis, so it's hosting a very, very stripped down version of Marlin.
Oh nice! And does it work well? Whats your planning? Are you planning to implement all the other features?
@NightFalcon650 Actually, yes, extremely well for the given application. The second Arduino can easily manage 4 Z steppers and 4 Z endstops for the corners of the bed, monitor chamber and hot-end temperatures, drive fans, and do other things that are less time-critical. If we needed to do auto bed leveling with the Z axis constantly adjusting during printing, we could probably achieve a reasonable synchronization by having the planner tell the second board where Z should move to, and how quickly. In the longer term, it will be interesting to see if we can have formal support for Marlin running on two boards, with tasks divided up in this general way. In my case, the second board also has a RAMPS, but if you didn't need extra steppers, you could do a lot just using a Teensy board by itself, or connected to a simple external PWM-able power circuit.
Sounds prommessing. It's just wat I intended with the feature request. Time critical parts (axes, stops) on the first board and the rest (feeders, heating, fans, extra connections) on the other. Hopefully your good work inspires others, so it gets realized in the final marlin version. I'm building a ultimaker 2 extended derivative and want to incorporate this idea.
@thinkyhead With your dual-Arduino setup, do you think that you could run a display over the second device? I am running into bottlenecks on my current setup and I think it is for a combination of factors.
I've implemented an SSD1351 OLED via SPI. The display looks good, once you pick a suitable color since the default color "1" really translates to dark blue in the 332 color space >.< The issue is that the combination of larger display (128x128) and 8bit color depth causes the printer to pause intermittently while doing screen updates. I'm wondering if your setup would help alleviate that if the slave could work asynchronously to do the screen updates.
I'd really love to add a color display controller to my setup, if it is at all feasible. I've already got some color hinting added to the LCD interface, but the pausing is going to be a showstopper. XD
Also, to run the 4X version of the u8g constructors, a boatload of RAM is used for display buffering. A slave Arduino would allow this to be implemented without running the master Arduino into the low dynamic RAM territory. Plus, running it on a Teensy would be amazing. We could create a whole new class of LCD control boards. :)
One thing I'm going to try for the UBL code on Deltas is to double these items:
#define BLOCK_BUFFER_SIZE 16 // maximize block buffer
#define BUFSIZE 4
That might help mask the CPU getting totally swamped some of the time. You might want to bump those up (double them) and see if it helps.
I'd really love to add a color display controller to my setup, if it is at all feasible. I've already got some color hinting added to the LCD interface, but the pausing is going to be a showstopper. XD
We need to get onto a 32-Bit platform where we have an excess of CPU cycles available.
display over the second device?
Yes, that would also be viable. But since the second board would be the slave, the menu system would need to be rewritten to provide commands to the main board, and the main board would have to poll the second board occasionally to look for those events. (I don't think you can run both the main and second boards in "slave" mode, but perhaps that is possible. I haven't tried it yet. I also haven't tried using Wire.onReceive()
from the master. Maybe that also works.)
the low dynamic RAM territory
I have doubts the library uses any dynamic allocation. It should be able to do its buffering statically.
@Roxy-3D : That's a pretty cute solution to the problem. I'll give it a go and see how it helps out. I agree on moving to 32bit platform, and I have a Due and soon a Duet board for testing. The HAL stuff is a bit beyond my scope of capabilities, unfortunately, and I'm kinda at an impasse with regard to updating the older Marlin4Due code.
Regarding the Marlin firmware, one of the reasons that I was wanting to use M100 so much is that I elected to use the extra buffering in u8glib (4X constructors) to cut down on the amount of data being sent to the display, and thus, reduce screen refresh times. This uses a ton of RAM, especially on this 128x128x8bit display... I get down to 700 bytes of RAM available for dynamic purposes, and I'm not sure what Marlin itself needs in a worst-case scenario... but I agree that u8glib shouldn't need dynamic allocation.
@thinkyhead : if you need anyone to test your code, let me know. I have a few Mega boards laying around unused... and although I was not at first very receptive of the concept of using two Arduinos, I'm now starting to see the potential.
update No go on doubling those values @Roxy-3D... not with double-buffering u8glib... -888bytes available XD I have 2K free without the added u8glib buffering, so I'll give it a run and see if I still have the pausing/stuttering.
Nope... small improvement, but I'm just asking too much of this Atmel. :/
I'm working on exactly this project now, and have just today extended the EXPERIMENTAL_I2C_BUS feature to support slave connections between two instances of Marlin, or to allow a single Marlin instance to act as a slave on the bus.
One thing to consider doing here: The I^2C is so slow... It might be ok to send commands (requests) to the slave. But if you really need both boards operating synchronized, It might be good to run a single GPIO line back from the slave to the master. The master could use I^2C to send everything, but then wait for the slave to pulse the GPIO line. That way both would be 'off to the races' at exactly the same time.
update No go on doubling those values @Roxy-3D... not with double-buffering u8glib... -888bytes available XD I have 2K free without the added u8glib buffering, so I'll give it a run and see if I still have the pausing/stuttering.
Even if you can't double buffer both of those values... Double buffering one of them might help. u8 needs to be re-written! It is way bigger (and slower) than it needs to be.
I wouldn't necessarily say that u8 is bigger and slower than it needs to be... but only a fraction of the library is leveraged by Marlin, so perhaps a stripped down version of u8 would be best. It would allow for easy addition of new display devices, while avoiding the need to do a complete rewrite.
@thinkyhead Do you have code available that we can play with? If it is stripped down, I might even be able to port it and get it to run on a faster board.
but then wait for the slave to pulse the GPIO line
@Roxy-3D Not a bad idea. I have also heard that SPI would be a lot faster. I chose i2c simply because we have that handy experimental i2c bus feature, but not something similar for generalized SPI. It was also simpler, it seemed, than trying to do RS485, which would have been required for the board we had intended to use.
the main board would have to poll the second board…
Or maybe not. If the master does set up an onReceive
handler, it doesn't need to have an ID so long as it does a Wire.requestFrom()
at some point to the slave it wants to listen to. My less-than-educated guess is that so long as the slave is "selected" in this way, whenever it does a Wire.write()
it ends up going over the line to the master, and the master will end up having onReceive
invoked.
Of course this means that Marlin would have to centralize all its i2c communication so it goes through the receive callback.
Of course this means that Marlin would have to centralize all its i2c communication so it goes through the receive callback.
I haven't been following any of the i^2c stuff... But my belief is that is all done with bit shifting and bit banging the I/O port. If that is true... We don't want to have this kind of stuff in an interrupt context. It would mess up the real time response of everything else that is time critical.
We don't want to have this kind of stuff in an interrupt context
No one suggested calling Wire library functions from interrupt context. Let's cross that sort of bridge when we come to it.
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.
Due to limitation of i/o Ports on a arduino we are limited in the use of sensors and actors. Idd would be nice when we could connect a second arduino (with or without a second ramps board) as a slave of the first. In that case we could connect more extruders (multi color/materal), fans, heatsensors, a second heat bed, auto leveling sensors etc.