MaikStohn / UP3D

UP 3D Printer Tools
GNU General Public License v2.0
79 stars 33 forks source link

Hardware or Transcoder X/Y lean issue on cylinders #18

Closed adrianbear closed 8 years ago

adrianbear commented 8 years ago

Hi Maik, I think there is a bug in versions 4.1 and 4.2 of the transcoder when printing cylinders (or lots of angles)

I've been calibrating my printer with some custom thin wall models (just squares) I made up and everything has appeared to be fine. I then upgraded from version 4.1 to 4.2. Assuming nothing related to transcoding had changed that would effect my calibrations, I started printing an S-plug. It printed the disk and disk with S hole perfectly, but the S on the top of the disk printed with a lean. See here for images => 1_print with 4 1

Thinking this might be a bug in 4.2, I downgraded to 4.1 and found the issue was still there and appeared across the entire print. This made me think maybe something was wrong with my hardware. So I printed it from the UP software and it came out perfectly, printed again from transcoder 4.2 and it leans again. See here => 2_splugs printed with various transcoder versions and upsoftware

I then printed my boxes and squares again with version 4.2 and they came out fine, so I printed the s-plug again but nope still has a lean. see here => 3_splugs and boxes printed with 4 2

So at this point I "think" there is no issue with the hardware but with printing circles from the transcoder, so I crafted a basic cylinder to test with. Results can be seen here => 4_cylinders printed with various versions and up software

A Cylinder printed with version 4.2 has a lean A Cylinder printed with UP software is perfectly upright A Cylinder printed with 3.0 is perfectly upright The same g-code used again with version 4.2 again has a lean.

This zip contains my gcode, umc code and the STL I used. Cylinder UMC GCODE and STL.zip

I am happy to be corrected and have it proven that my printer has a slip of some sort, but this looks like a bug in the latest transcoder versions to me (at least 4.1 and 4.2). The other thought that has crossed my mind is maybe there is some "hack checking" going on from inside the UP firmware on the printer itself. I sure hope this is not the case....

Thanks Adrian

MaikStohn commented 8 years ago

Hello Adrian,

for sure this is not a hardware or protection issue. I had this a lot during development. It can be fixed for sure.

I can see the problem in back translation of the umc. Stay tuned...

Maik

adrianbear commented 8 years ago

No Worries, I just finished trying a different size cylinder to see if it was something about the shape that strained my printer. The larger cylinder just exaggerated the issue and each layer is about 5mm off from the previous.

I also noted, that the stepper motors (X and Y axis) were making the occasional click as they ran the perimeter, which they don't do when printing cubes (at least not noticeably).

Hope this helps, thanks

Adrian

adrianbear commented 8 years ago

Hi Maik,

Yep it seems version 0.3 is good but 0.4x is not.

I am already printing at a pretty low speed. My default print speed is 3600 mm/min and x/y movement speed is 4800 mm/min, but I have a minimum layer time of 15 seconds and tell it to allow speed reductions dwn to 10%. I'll try a print at 800 mm/min and let you know. Is there anything I should be looking for in particular?

Thanks

adrianbear commented 8 years ago

Hi Maik,

The cylinder print I produced after reducing the x/y movement speed to 800 mm/min was identical to my previous failed prints (seen in pictures above). However I then tried increasing the speed. I returned the x/y movement speed to 4800 mm/min, but changed the Outline and Solid Infill underspeed percentages from 50% up to 80%. The resulting print came out beautifully with no lean to it.

Is this the type of result you were expecting? I hope it's helpful?

Thanks Adrian

adrianbear commented 8 years ago

Hi Maik,

A little more testing to provide a good and a bad Simplify3d factory file for you. Simplify3d factory files => Good and Bad Factory files.zip

And wow the UPBox can print fast. Thanks Adrian

MaikStohn commented 8 years ago

I checked forward / backward translation of the umc file the complete day and can not find any miscalculation. I thought I saw something this morning but it was caused by a mistake form me (convg uses steps/mm for mini but your box is having different values... we know this already).

Based on your findings (click sounds, faster speed works) I will have a look into acceleration calculation again.

BTW: 4800mm/min = 80 mm/sec for x/y movement ? This is still slow... I use at least 120mm/sec (7200mm/min) for all of my printer. For print speed (fast infill) I usually use 60 to 70 mm/sec (3600mm/min). And for quality looking perimeter 30 mm/sec (50%)

Maik

adrianbear commented 8 years ago

Hi Maik,

Yep, I perform most of my printing rather slowly. I focus heavily on the quality and accuracy of the print rather than the speed. This is one of the key reasons I am so keen to use Simplify3d against my UPBox, the UP Software just doesn't supply enough control.

The key features of Simplify3d that I use in priority are

These are (as you know) all made possible with your transcoder.

In short the ability to print slowly is important to me. Would it be possible to expose your transcoder variables in a config file (i.e. variables for Acceleration and/or motor steps etc etc, per model type)? You could probably include your nozzle height and input/output files names in this too. Then I could play with the values myself without having to figure out how to make changes and compile your code (and likely screwing it up for other models). Plus you'd likely be able to support any new UP models that are not released yet without changing the code. :)

Thanks Adrian

adrianbear commented 8 years ago

Hi Maik,

I have spent all afternoon adjusting speed settings to figure out what's going on. I even recorded my tests and results image

As you can see I started with a failing speed, then went to a passing speed, then reduced speed to find the fail point. But had to make some other speed changes along the way to get perimeter speed decreasing correctly. In the end they all passed. So maybe there is a rounding issue with the acceleration calc or something that only comes into effect given specific settings.

Either way, I think I can work around the problem for now.

Thanks Adrian

MaikStohn commented 8 years ago

Hello Adrian,

thanks so much for your tests. I revised acceleration calculation and think I found a small mistake. I do several test prints right now to check if the change has side effects or just makes it better.

Maik

MaikStohn commented 8 years ago

I changed acceleration calculation and fixed a potential bug. I also lowered acceleration a bit to have more smooth moves. So I hope v0.5.0 fixes the missed steps you had (which caused the lean issue)

Maik

adrianbear commented 8 years ago

Hi Maik, Preliminary test looks good. But just in case...is there a way I can get the UMC code from an UP Software print? I assume you would then be able to decode it to determine the acceleration values used by the native software?

Thanks Adrian

kscheff commented 8 years ago

@adrianbear you can capture the "umc" output in Windows via the Fixup3d DLL (modified winusb.dll). FixUp3D generates a debug folder called "UpUsbIntercept" and places the print data in a file called MemDump.dat. You need to delete this file before you want to capture a single object output, since it collects all data across multiple prints. I usually rename the file after each print to objectName.umc.

Next you can feed the captured file to Maiks tool called "convg" by calling it from the command line. convg objectName.umc >objectName.gcode

I made myself a modified version of convg to output print data in a spreadsheet like form, so I can use Excel to to analyze and calculate acceleration etc. but this approach needs some tweaking of the data sets and I am not sure about its results. So I have turned to standard g-code analyzers like gcode.ws. The issue on the resulting gcode is, that all lines are broken up into small little different speed/acceleration segments (that is what the UP motion planner spits out). So it is not so easy to extract speed an acceleration parameters. I don't have Simplify3D handy.

Update: Here is the test data I have captured with a 10x10x10 cube with different speed settings and converted via convg, further translated to a spread sheet. Please note that the slic3er generated data set is based on an old version of up3dtranscode, so please ignore. See visuals from the same data set generated by gcode.ws here #15

MaikStohn commented 8 years ago

Hi kscheff, this is great.

I'm looking at this numbers all day long and might overlook something. I hope you will be able to understand and re-check the acceleration / speed things.

The calculation in "convg" should be considered reliable (i checked it with the real machine and upshell down to a single step).

Maik

kscheff commented 8 years ago

Here is a chart I created from my test cube with the UP software slicer in fine, normal, fast mode: chart_speed_vs_length

Update: What wonders me here is that the maximum segment lengths in Fast mode is larger than in Normal than in Fine mode.

The chart could be explored online here: https://docs.google.com/spreadsheets/d/1CGauKWOO-7a-yncpVThsTYFuhOoGTthZgEveb8qjkKk/pubchart?oid=2028505029&format=interactive

MaikStohn commented 8 years ago

Hi,

2000 mm/min max speed? This would be 30mm/sec only. So looks like we print much much faster now.

EDIT: Of course it can not go much faster on a 10mm line...

I watched a normal UP printing process for 1 hour now :-) I'm pretty sure our acceleration of 3000 or 2000 ist still a lot higher than UP software is using. I guess from looking they use <1000 mm/sec^2.

So this is something to discuss... Faster acceleration gives sharper corners and less blobs at edges but it will also make the printer move more rough (you can hear it mostly when it decelerates to full stops making little "bang" noises).

adrianbear commented 8 years ago

Hi Maik, I've had another couple of failures (using UP3DTOOLS_WIN_20160501_v0.5.0) 20160503 aircraft parts

Please note in the picture, both prints had two parts per print job and the larger parts failed, not immediately, but shortly after the first smaller part had completed. I am still not 100% sure this is not an issue with just my printer....

I have just run a series of test prints using the UP Software and zipped up the complete FixUP3d debug folders. I also include screenshots of various settings screens in the UP Software so you can see my setup and the UP software files. RAW Data from an UPBox.zip

Also, I remember previously printing a large box using the UP Software that consumed almost the entire print bed. I could visibly see it accelerate and decelerate from one side of the bed to the other.

Hopefully this helps. Thanks Adrian

adrianbear commented 8 years ago

Hi Maik, By default I think the acceleration settings should match those from the native UP Software. At least we know they work and have been thoroughly tested. But if you think other users might want different options, you could expose the settings as a parameter or in a config file. Adrian

MaikStohn commented 8 years ago

Hi Adrian,

the problem is I just not found the real values of acceleration inside original UP software (yet). I thought I found them (3000mm/sec^2) but this looks much to fast. That's why I lowered them in last version (2000) but they still look to fast.

What I observed in your pictures is that the problem happens after a "longer"? print time. The reason for this is usually that the stepper motors getting warmer/hot and loose torque. This can be compensated with either cooling -or- moving + accelerating slower.

Maybe you printed same object 2 times. If so, can you check if the problem didi occur at the exact same position or maybe on a different one. If it slips at different positions it would rule out a calculation error.

Maik

MaikStohn commented 8 years ago

I'm thinking a lot about this acceleration thing over the last days,

maybe @kscheff or somebody else could assist me with this.

What I found out about the internal UP CPU handling acceleration / moves is the following:

CMD 4 (extrusion move): p1,p2,p3,p4,p5,p6,p7,p8 (16 bit values) p1 = how often this (block) is executed p2 = the frequency/time for every execution X:p3,Y:p4,A:p5 = steps x 512 per execution (x512 is to have a fraction) X:p6,Y:p7,A:p8 = steps x 512 added to (p3,p4,p5) per execution (x512 is to have a fraction)

Example: p1=5 ==> do 5 times p2=10000 ==> 10000 (time for block relative to 50MHz CPU frequency) p3,p4,p5 all 0 --> no starting speed for (X,Y,A) p6=1,p7=2,p8=0 --> every block execution speed will be increased by this value ==> execute 0: speedX=0,speedY=0,speedA=0 +1,+2,+0 execute 1: speedX=1,speedY=2,speedA=0 +1,+2,+0 execute 2: speedX=2,speedY=4,speedA=0 +1,+2,+0 execute 3: speedX=3,speedY=6,speedA=0 +1,+2,+0 execute 4: speedX=4,speedY=8,speedA=0 +1,+2,+0 (??? not sure if this happens)

p3,p4,p5,p6,p7,p8 can be positive and negative (16 bit integer)

512,1024,... is 1 step

fractional parts are calculated during this block, but discarded after block finished

they use "floor" to always round down (which is horribly wrong for negative numbers...)

Maik

kscheff commented 8 years ago

@MaikStohn

Yes, that is an interesting subject here.

So far I cannot make much sense from the data I get with my simple test cube 10x10x10 sliced by UP in fine/normal/fast mode. As noted I have captured the data and feed through convg for further analysis.

CMD 4 is the main command for moving and extrusion right? My first focus would be on the question why CMD 4 has a repeat factor p1 so prominently placed? The p1 multiplier only results in a linear move in the same direction with the same acceleration. I can only guess what the reason for this factor is:

The motor drivers are usually controlled by a timer interrupt and use a discrete frequency, right? The main motor driver control interrupt does not handle any acceleration, it is driven by a fixed but controllable frequency. By using the p1 factor one can assume that this mechanism is used to produce discrete acceleration steps for the motor driver. The machine heads weight and thus the dynamic of the system is then the result of these discrete stepped acceleration approach….

So one way of handling this would be to use each segment from the motion planner and break it up into a number of segments to smooth acceleration (p1). How many number of segments would be required depends on the maximum tolerable acceleration steps of the UP mini.

Can we see that UP uses P1 > 1 in its output file? And if so, what is the max acceleration or step size here in the different modes. See below for analysis of the P2 and P2 parameters.

… so that was going through my head driving on the autobahn the last two hours….

Best regards Kai

kscheff commented 8 years ago

After dumping the MoveL (CMD 4) command in convg to the G-Code output as a comment I noticed that your 0.5.0 code generates negative p2 int16 codes. May be that is an issue of signed vs. unsigned 16 bit interpretation. The original UP software slicer does not create values >25000 and thus avoids this conflict.

Please see attached the filter MoveL commands: Cube_10x10x10_movel.zip

kscheff commented 8 years ago

I also noticed for MoveL command the UP software uses only values between 2 and 500, whereas up3dtranscode host stepper uses 1 to 4470 in the example above. This might also be a source of trouble for the UP firmware.

Here are some diagrams showing P1 and P2 for a 10x10x10 Cube

Generated by UP Software 2.18 in Normal mode: test_normal

Generated by Slic3er and Transcoded by up3dtranscode 0.5.0: test slic3r

Further I compared the P2 difference (acceleration between segments) on the same test cube:

UP Slicer Normal mode test_normal_p2_diff

UP Slicer Fast mode test_fast_p2_diff

Slic3er with up3dtranscode 0.5.0 test_slic3r_p2_diff

adrianbear commented 8 years ago

Hi Maik, kscheff,

Have you guys reproduced the issue with your printers? I'd like to point out, I have had no issue with cubes, only curves. This suggests to me that if the issue is related to acceleration/deceleration settings, it seems to only be relevant to accelerations/decelerations from/to a non-zero speed in either axis. The "lean" is always to the rear left of the printer and "appears" to be exactly 45 degrees (i.e. effects both axis at exactly the same time, by exactly the same amount).

It also seems to be more prevalent the slower I print. The blue prints I have pictured above, the gcode slows after the first smaller part to keep the layer time above 15 seconds. This is when the print starts to fail.

Also looking closely at the lean on the large aircraft print, I can see the lean occurs for a number of layers, then prints straight again for a number of layers, then leans again for quite a few layers. This suggests to me we have a step calculation/rounding issue.

Please stop me if I am just stating the obvious to you guys? I guess I am just trying to re-assure myself the issue is not just with my printer.

Adrian

kscheff commented 8 years ago

@MaikStohn I see also occasional MoveL commands with P1=1, P2=100 these are the very short correction moves by defining X_INSERT_STEP_CORRECTIONS. May be the UP CPU isn't fast enough to catch up here. The min value for P2 the UP Software generates is 14650 on my test cube in normal mode and 20350 in fast mode.

Update: this brings me to another question: why should we correct a calculation error with an extra little segment? This may be corrected in the next segment, so you can carry the error forward and defuse it there. This would contribute to a little smoother path.

I am trying to calculate the V entry and exits speed along with the acceleration for each segment MoveL command. I hope I understand it right, my formula is like this:

Time tick in Segment: t = P2/50e6 [in seconds] V entry: P3/t [in mm/seconds] V exit : V entry + (P1 * P6 / t) [in mm/seconds] V avg : (V entry + V exit)/2 [in mm/seconds]

Then I saw that V exit is different to the next segment V entry speed, thus there is an acceleration step forced to the printer. I calculated each of this differences in the spreadsheet. Here is the comparison of the different graphs:

text cube UP 2.18 Normal speed - acceleration segment to segment test_normal_accx_seg_to_seg

test_normal_avgvx

Whereas the test cube sliced with Slic3r and transcoded via up3dtranscode 0.5.0 looks like this: test_slic3r_accx_seg_to_seg

test_slic3r_avgvx

The segment to segment speed jump is via up3dtranscoder 0.5.0 about 10x higher than in the UP software 2.18 normal speed mode.

MaikStohn commented 8 years ago

Hi,

@adrianbear I printed many many very nice parts with v0.5.0

@kscheff

CMD 4 is the main command for moving and extrusion right? Yes CMD4 is the only command which allows fine/synchronized control for X/Y/A motors

My first focus would be on the question why CMD 4 has a repeat factor p1 so prominently placed?

I try to explain more what I understood so far:

p2 is the PWM timer generator period (base frequency) p3,p4,p5 tells the PWM how it should emit step pulses, to have also a fractional part this value is multiplied/divided by 512 ==> MAX: 32767 means 1 step (must be on and off) every PWM cycle = fastest( -32767 same but direction output reversed so motor drives other direction)

So maximum would be 32768 / 512 = 64 steps (/854 steps/mm = 0,075mm this is a very short distance... That's why p1 comes into play. It is just says how many times the above cycle is executed ==> p1=100 would then be 6400 steps (/854 steps/mm = 7,5mm) much better

Now to p6,p7,p8, This values are used for acceleration/deceleration. With every p1 loop this value is added to p3 / p4 / p5 (which increases/decreases speed ==> exactly what acceleration/deceleration is).

In the latest MAC-Release of UP-Studio Tiertime was friendly enough to supply a .DSYM file ;-) which brought real names to all variables inside of the software. From this I created a file in "notes" directory called "structs.txt". There you can find the real names Tiertime used or p1,p2,p3.... for CMD4:

6798 MoveCmd       00000010 Auto struct 
{
  unsigned __int16 SegNum;
  unsigned __int16 SegPeriod;
  __int16 XSpeed;
  __int16 YSpeed;
  __int16 ASpeed;
  __int16 XAcc;
  __int16 YAcc;
  __int16 AAcc;
}

==> p1 is unsigned int 16 ==> can be any value between 1 and 65535 Inside of UP-Software is a logic to limit p1 to max 501 (for no reason!) They just do it to prevent any kind of overflow since their calculation does not have a check and recalculation.

==> p2 I experimented with the printer and found that the smallest value is 100. Any value below this will just ignore the block. During various UP software versions this value changed from values around 25000 to values around 10000. But best way would be to choose the correct PWM base frequency which best fits to the values to have the smallest rounding errors (remember all 3 axis must be synchron). For slower/faster moves it's better to use faster/slower PWM base frequencies. So why limit p2 to some range if we can use full spectrum.

The " X_INSERT_STEP_CORRECTIONS" was an idea which I implemented to have 100% step accuracy (which is not possible with 1 PWM base timer and 3 different output channels). It just pushes the missing step immediately (and as fast as possible: p2=100). After some testing I found that the compensated error is almost not existent and disabled it (it's disabled with the define). What you suggested (sum up the errors and compensate with next move) is implemented already. They are tracked within gx,gy,ga.

Anyway it looks like I made a small mistake in v0.5.0 when I calculated the acceleration value. v=a*t ==> a = v/t instead I used a=(v/2)/t. It was correct in previous versions but during some experiments I changed it and copied the wrong block. (Will fix this later today).

So things left I'm thinking about:

Weekend comes and I will have some time :-) I have a good feeling to solve this completely.

MaikStohn commented 8 years ago

Hi,

I reworked the complete calculation. Previous versions had serious miscalculation of acceleration values... I will do some test prints and if all is well a new version will come shortly.

@kscheff convg also had a small bug. the int16_t for p1 and p2 need to be changed to uint16_t otherwise an overflow in feed rate (speed) calculation can happen (also will be fixed in next version).

Maik

kscheff commented 8 years ago

Hi Maik,

I saw that int16 issue, it's also on the parse side. Regarding the accelerations, I have a spreadsheet to feed the MoveL data and calculate the acceleration parameter. The previous graphics are driven from that. I can share this in a gsheet on interest.

The thing I wanted to point out is that the UP software uses the P1 and P2 parameters in a more limited range. The UP firmware versions are probably only tested against their own slicer and planner. By using a wider range we may provoke issues, firmware bugs, which do not show up on all versions of the firmware. At the end the firmware will have its issues as well. So I would be more conservative with these parameters, eg:

Limit P1 between 2 and 500 Limit P2 between 10000 and 25000

The UP planner seems to issue multiple P1=500 commands to run a long segment. There might be a firmware restriction (may be older ones) driving this behavior.

The P2 parameter translates to a timer setting and most likely triggers an ISR. So low P2 settings might give the firmware not enough time to service all required tasks, especially considering asynchronous tasks like USB or SD Card. These type of errors don't show up easily and frequently.

The segment to segment speed jumps are also much higher on the 0.5.0 version than what UP software generates. So here again I would be more conservative. At the end we don't know exactly the design limits of the motor controller or the mechanics (oscillation, strength). I am sure tiertime is not artificially limiting the speed when it's not needed.

As you can read, I am a bit conservative. I have just seen so many firmware issues on embedded chips in my life (working many years on semiconductor side with USB chips, applications, embedded audio DSPs, PCIe bridges).

Am 06.05.2016 um 20:07 schrieb Maik Stohn notifications@github.com:

Hi,

I reworked the complete calculation. Previous versions had serious miscalculation of acceleration values... I will do some test prints and if all is well a new version will come shortly.

@kscheff convg also had a small bug. the int16_t for p1 and p2 need to be changed to uint16_t otherwise an overflow in feed rate (speed) calculation can happen (also will be fixed in next version).

Maik

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub

MaikStohn commented 8 years ago

Hi, I just tested... and there is no limit in firmware for P1 and P2. I also pointed out earlier, that older UP versions used much different values.

Everything runs smooth now.

I also manually recalculated acceleration UP software uses: 1500mm/sec^2

formula is easy (took me some time to figure out but is easy):

t = p1xp2 / 50000000 (50MHz) s = (p3xp1 + p6/2xp1xp1) / 512 / 854 (512 for fraction, 854 for steps/mm) v = s/t a = v/t

I just took some captured data from UP software: p1=4, p2=24300, p3=0, p6=125 ==> t = 4x24300 / 50000000 = 0.001944 sec s = 0.00565354 mm v = 2.9082 mm/sec a = 1495,988 mm/sec^2

:-)

I even increased the p1 and p2 calculation to use maximum values (near 65535) since this will dramatically reduce the calculation error.

I tested it with several prints and did not encounter any problem by now.

So no more mysteries.

New version in a few minutes.

@kscheff P2 is the divider from CPU base frequency for a PWM generator (if you read the spec of the UP CPU you can see that it takes a 16 bit (unsigned) value ==> full 65535 range). So no ISR, it's a good 32 bit ARM MCU with a lot of horse power (not to compare with the 8Bit Atmel stuff used on Ard*_o). And P1 is a loop counter which I tested manually to take >32767 values. BTW: All 32 bit ARM CPU have proper DMA support, nested_ interrupt controller (higher prio interrupt can interrupt another interrupt :-) ) and many more features. I use to program them all day long. So it's really almost impossible to create something with bad timing, especially if you use the hardware macros of the CPU to achieve the tasks.

Maik

kscheff commented 8 years ago

@MaikStohn I just ran my test cube with the new 0.6.0 version to my spreadsheet. Here you can see little fancy high accelerations. The calculations are done like you suggested before. The graph of the acceleration for x, y, e shows regular high peaks, see yourself:

https://docs.google.com/spreadsheets/d/1aIxE2mKu8E7UoCt6WrIOvLIWAB3qfg3n4s7UbH98FRA/edit?usp=sharing

adrianbear commented 8 years ago

Hi @MaikStohn , Sorry Maik, but the issue still exists in version 0.6.0.

I've just run a test of my cylinder using the speed settings I need for the aircraft prints and I get the following. from front while printing

I have zipped up the cylinder STL, input gcode, output upcode and the Simplify3d factory file for you to check out. 060 Lean Examples and Data.zip

Is there anything else I can provide that might help? Is it possible the UPBox uses different stepper motors than the UP machines your testing with? Are you able to reproduce my issue using the simplify3d factory file I've included?

Thanks Adrian

adrianbear commented 8 years ago

Hi @MaikStohn,

Do you make sure the speed and accelerations have reduced to zero before making a layer change?

Adrian

MaikStohn commented 8 years ago

Hi,

@kscheff Thanks for the spread sheet. It looks like this happens since "time" is very small (<0.001 sec). I will check with debugger now when this calculation happens.

@adrianbear Your question is indeed interesting. The calculation and output ensures that zero speed is reached, however the machine might not have it at the same moment. Since the Z-Move must use another command without this speed/acceleration/... calculation it might be that this two commands interfere. In original UP software I saw that a small pause (0.01 seconds) is inserted from time to time. I thought this is done for waiting for extruder to have some time to squeeze more material when it reaches an end.

But with your comment I was checking again and it looks like they are inserted just after extrusion moves finished right before a normal move is executed. This might be the problem we looking for your printer.

kscheff commented 8 years ago

I have updated the Google Sheet with an additional chart showing the acceleration over the segment length. There are optional Filter Views added to exclude small segments. This gives more information regarding the acceleration used.

https://docs.google.com/spreadsheets/d/1aIxE2mKu8E7UoCt6WrIOvLIWAB3qfg3n4s7UbH98FRA/edit?usp=sharing

Further I have created a 20x10 cylinder like @adrianbear did. Once I sliced and captured it via UP Software 2.18 and compared it to Slic3er transcoded by up3dtranscode 0.6.0. I put both version in a similar spreadsheet like my test cube. Here you can see the results:

https://docs.google.com/spreadsheets/d/1rp_d07f-jtyZf9WVEKS_4baYSbopAWFi5qLRXsVwlEc/edit?usp=sharing

https://docs.google.com/spreadsheets/d/1ozPkWjqSpDPYXp41caJWurU2nG5iw2Y1nv8MnsFS6mg/edit?usp=sharing

MaikStohn commented 8 years ago

Hi,

@kscheff I looked at the excel files and everything looks good. I can not see wrong calculation. The "spikes" you see is when there is very small time segment and a very small speed change. Stepper motors can handle this kind of changes without acceleration (a = infinite).

So I follow the path from the suggestion from @adrianbear

Maik

kscheff commented 8 years ago

@MaikStohn I am looking at you calculations in hoststepper.c. Here I found some redundent calculations for P3:

    double sa_x = (v_exit-v_entry)*t*pl_block->factor[X_AXIS];
    int64_t p6 = (int64_t)(sa_x/(p1*p1));
    int64_t p3 = (int64_t)(s_x/p1) + (int64_t)((sa_x-p6*p1*p1)/2/p1);

Resolving sa_x from p6 (middle line) results in: sa_x = p6 * p1 * p1

inserting this into the calculation of p3 gets the following: p3 = s_x/p1 + (p6 * p1 * p1 - p6 * p1 * p1) / 2 / p1

now the middle p6 term in brackets equals to 0, so we can shorten the calculation to: p3 = s_x/p1

I tested by printing the values inside up3dtranscode via: printf("Check p3: p1 = %u, p2 = %u, p3: %d - %d = %d\n",(unsigned int)p1, (unsigned int)p2, (int)p3, (int)(s_x/p1), (int)p3 - (int)(s_x/p1)); The result between your p3 calculation and my simple one is mostly 0, sometimes there are single and double digit differences < 50. I guess this is due to rounding issues on the complex formula. This contributes to some error here.

Here is the g-code source and the output of the modified up3dtranscode to show the difference: p3check.zip

Same situation for the other axises on P4, P5.

MaikStohn commented 8 years ago

@kscheff This is added to compensate the rounding error. Like you found yourself it is not always 0. Without this compensation you would get really ugly prints.

kscheff commented 8 years ago

@MaikStohn The rounding compensation comes later into play:

    //calculate xsteps generated like mcu in printer (THERE IS A BAD *FLOOR* ROUNDING INSIDE!)
    int64_t sx = floor((float)((p3*p1+p6*p1*p1/2))/512)*512;
    int64_t sy = floor((float)((p4*p1+p7*p1*p1/2))/512)*512;
    int64_t sa = floor((float)((p5*p1+p8*p1*p1/2))/512)*512;

    //calculate mcu rounding error compared to real steps required
    g_ex += s_x + sa_x/2 - sx;
    g_ey += s_y + sa_y/2 - sy;
    g_ea += s_a + sa_a/2 - sa;
MaikStohn commented 8 years ago

Sorry, this was a confusion from me.

p3,p4,p5 can be seen like speed value. The term in the end is needed to calculate acceleration / deceleration. Since deceleration also comes with rounding errors but you want to have 0 speed at end you must compensate this error. So this is doing a small trick: It just adds/subtracts from the initial speed a very small value so the exit speed is matched properly. Since the value is very small no acceleration/deceleration is required.

This means your output matches the output I had before I added rounding error compensation.

MaikStohn commented 8 years ago

@adrianbear : I implemented the same wait before layer change like in up software (0.001 seconds). Hope this has an effect and will solve the "cylinder" issue. New version v0.6.1 contains this addition.

@adrianbear + @kscheff : I highly appreciate your help and effort to make the tools better. During discussion new ideas come up. I'm also happy to answer any question and discuss about the calculation and in case I'm wrong with something please tell me.

Maik

kscheff commented 8 years ago

@MaikStohn Understood. I checked for the sake of interest if there is a better matching of p1/p2 possible in order to minimize the rounding error. As a result there is some improvement in a smaller speed bump between segments. Here is the histogram of the improvement:

histogram p1 p2 error

Here is the modified code in hoststepper.c:

void st_create_segment_up3d(double t, double v_entry, double v_exit)
{
  //==> tmax = 65535*65535 / 50000000 = 85.8 sec. per segment
  int64_t p1 = 1+(int64_t)(t*F_CPU)/65535;
  int64_t best_p1 = 0;
  int64_t first_p1 = 0;
  bool    end_fit = 0; 
  double ds;
  double best_ds;

  //s = v*t
  //s linear speed
  double s_x = v_entry*t*pl_block->factor[X_AXIS];
  double s_y = v_entry*t*pl_block->factor[Y_AXIS];
  double s_a = v_entry*t*pl_block->factor[A_AXIS];

  //s acceleration
  double sa_x = (v_exit-v_entry)*t*pl_block->factor[X_AXIS];
  double sa_y = (v_exit-v_entry)*t*pl_block->factor[Y_AXIS];
  double sa_a = (v_exit-v_entry)*t*pl_block->factor[A_AXIS];

  for(;;)
  {
    int64_t p2 = (int64_t)(t*F_CPU/p1);

    //minimum timer value UP CPU can use is 100
    if( p2<100 ) p2=100;

    int64_t p6 = (int64_t)(sa_x/(p1*p1));
    int64_t p7 = (int64_t)(sa_y/(p1*p1));
    int64_t p8 = (int64_t)(sa_a/(p1*p1));

#if 1
    int64_t p3 = (int64_t)(s_x/p1) + (int64_t)((sa_x-p6*p1*p1)/2/p1);
    int64_t p4 = (int64_t)(s_y/p1) + (int64_t)((sa_y-p7*p1*p1)/2/p1);
    int64_t p5 = (int64_t)(s_a/p1) + (int64_t)((sa_a-p8*p1*p1)/2/p1);
#else
    int64_t p3 = (int64_t)(s_x/p1) ;
    int64_t p4 = (int64_t)(s_y/p1) ;
    int64_t p5 = (int64_t)(s_a/p1) ;
#endif

    //test format limits
    if( (p3<-32767) || (p3>32767) || (p4<-32767) || (p4>32767) || (p5<-32767) || (p5>32767) ||
        (p6<-32767) || (p6>32767) || (p7<-32767) || (p7>32767) || (p8<-32767) || (p8>32767) )
    {
      p1++;           //increase segment repeat count and try again
      continue;
    }

    //calculate xsteps generated like mcu in printer (THERE IS A BAD *FLOOR* ROUNDING INSIDE!)
    int64_t sx = floor((float)((p3*p1+p6*p1*p1/2))/512)*512;
    int64_t sy = floor((float)((p4*p1+p7*p1*p1/2))/512)*512;
    int64_t sa = floor((float)((p5*p1+p8*p1*p1/2))/512)*512;

    //calculate sum of absolute error on all axises
    double ds = fabs(s_x + sa_x/2 - sx)
              + fabs(s_y + sa_y/2 - sy)
              + fabs(s_a + sa_a/2 - sa);

    // after first fit we initialize to seach for minimum error
    if (best_p1 == 0)
    {
        first_p1 = best_p1 = p1;
        best_ds = ds;
    }

    // check if we should continue searching
    if (!end_fit && ds > 100)
    {
        if (best_ds > ds)
        {
            best_ds = ds;
            best_p1 = p1;
        }
        p1++;
        // we either stop at the end of scale or when iterated another 1000 times       
        if (p1 > 65535 || p1 > best_p1 + 1000)
        {
            p1 = best_p1;
            end_fit = 1;
        }
        continue;
    }

    //if (first_p1 != p1)
    {
        printf("P1: distance to first match: %u, %.4f\n",(unsigned int)(p1 - first_p1),ds);
        //printf("P1: first match at %u, best match at %u\n",(unsigned int) first_p1, (unsigned int) p1);
    }  
MaikStohn commented 8 years ago

@kscheff: I think you try to optimize something which does not need optimization. Do you know how acceleration is implemented in all 3D printer and other machines? Speed is not increasing linear, instead every 1/100 second the speed is increased (in your eyes a "speed bump"). Stepper motors can do this kind of jumps in speed, as long the jump is not to high. For instance if you would limit maximum speed to 20mm/sec you would not need acceleration at all. The stepper motors simply can jump to this speed. Only in case you want to achieve much higher speeds acceleration is needed.

Anyway, with the last changes (I reduced planner syncs and even got a better error correction working) I was able to make a "tilted" test print on my printer. The same object gcode printed fine with all previous versions. So now I have a test object myself and can try to find the cause.

kscheff commented 8 years ago

@MaikStohn After seeing the slight improvement on the spreadsheet, I was asking myself if its worth... I started with a single axis in mind and thought I can reduce the error to 0, but that is not the case, let alone all 3 steppers. Since I invested the time, I put it up here for "discussion".

Steppers are driven with discrete steps, so there is always some kind of "hard" acceleration happening. However it should always be the design goal to keep it as smooth as possible to avoid high torque which may lead to vibrations (I saw some ringing on the perimeters when printing eg letters on a vertical surface).

For my taste Slic3er in combination with up3transcoder runs much more rough (meaning there is more acceleration, speed), but the resulting total print time doesn't benefit from it. Its actually slower. And as @adrianbear stated as well, I am also looking into quality surfaces and quality comes in big when the print head runs smoothly. I continue to dig into the code for better understanding what is going on...

adrianbear commented 8 years ago

Hi @MaikStohn, @kscheff,

I'm trying to avoid getting myself into the code and I'm focusing on just on testing for you. I'm running the same test again with version 0.6.1 now, but looking at the gcode preview (gcode=>upcode=>gcode), it sure looks pretty now :) . Not really sure why the speeds would change so much on a single circular run, but we'll see what happens.

image

Adrian

adrianbear commented 8 years ago

OK, It seems whatever was changed between version 0.6.0 and 0.6.1 has amplified the issue. wp_20160508_011 wp_20160508_012

MaikStohn commented 8 years ago

Hi,

actually this is great. It shows that the last change has influence on it. It rules out any machine limits like skipped steps due to wrong acceleration.

Three things I have in mind could be cause for this:

Since I can test now myself I will do some experiments and report back.

MaikStohn commented 8 years ago

After having a very close look to my previous prints I found that they are lean as well (very very small, but it exists). I did some experiments today (used UP internal move-direct for all travel moves) but the error is always present. Right now it looks like this has something to do with rounding at the end of a move. Internally I think the UP stores the actual step only (without the *512 for fractional part). During a segment output it uses the fractional part to sum up for the complete p1 period. But what happens after the move is complete? The remainder is thrown away? Somehow the internal position calculation in UP is confused and also wrong after we supplied some of our values to it. I changed all travel moves to up internal ones but the tilt was still present. This let's me think we supplied values the motor was not driving but the up internal position calculation thought it moved (a very small bit).

I think best would be to create a test program just driving around and compare reported values from machine with pre calculated values. Then doing all kind of moves at all kind of speeds to identify the problem.

yanivg101 commented 8 years ago

I think that the calculation is done with big precision but the software writing round numbers to the SD but use precision internally. (and maybe I just write nonsense...)

MaikStohn commented 8 years ago

@kscheff I think it might be a deceleration underflow. I need your excel kung foo :-)

Example: Deceleration: p3,p4,p5 is initial speed p6,p7,p8 is subtracted from this initial speed during the segment. After looking at the machine and some experiments I saw a strange behavior: When I "accelerate, move, decelerate" but decelerate a bit to much (e.g. initial speed to small) then the move ends with "bang noise" and reversing of direction for some steps. This reversed steps are visibly executed but the UP internal position is NOT updated. So based on this observation we know now that there are parameter combinations which lead to movements but not to internal position updates. Since a Z move requires a direct move (which uses UP internal position) this is a good candidate for the lean / tilt we are looking for.

Maik

kscheff commented 8 years ago

Hm, this means we are looking for segments which change the direction inside a single move-l command? Does the planner spit out moves with V entry, exit with different sign? I have put Adrians g-code from the above report to a spread sheet and calculated all parameters. Then I created a term to identify if Ventry and Vexit have the same direction and filtered all values which do not match this criteria (column AA is the magic here): https://docs.google.com/spreadsheets/d/1t1hsaOaZaMM1-rGaGgAcWLs8SaWcyI8aATZMylzoyZk/edit?usp=sharing

I checked the same formula on original captured UP data, those type of moves are as well existing. I also checked if an Vexit to a next segment Ventry changes direction, this is also the case. Both types of moves are in the order between 200 and 300 moves from a total of 10000 Move-L commands.

MaikStohn commented 8 years ago

@kscheff We are not looking for planner creating this. Looking for when error compensation is doing this...

I found that the output contained some 0 segments (p3-p8 all 0), removed this I also found out that for p2<800 not even a single step would be in output, not putting this to output anymore, just do the error tracking Last thing I put inside was to not do error correction on decelerations (printer runs a lot smoother now)

To my surprise, I got a very straight print this time :-)

I will put it online in a few minutes.