Analysis of the principle of 3D printer

This article will explain how a 3D printer works by implementing a 3D printer firmware. Click on the article index for a quick jump. The code address

The cause of

Hi, I’m Arnold. I bought a 3D printer online last year. The configuration is very simple, and you can start printing in 30 minutes. Since then, I have a new hobby is squatting in front of the printer and watching the parts being knitted stitch by stitch, watching and wondering how can I print all kinds of complicated 3D models with only four motors turning forward and backward.

So I began to wonder how it was possible, but I had no idea and didn’t believe I could figure it out. First of all, if I take this machine apart, do you think I can put it back together? If it doesn’t fit back in, there’s no way to tell. Even if the manufacturer is willing to help, the factory is thousands of kilometers away, not the neighborhood next door, it is difficult to help. Secondly, the software part I also do not know how to achieve, although I use Marlin firmware code is open source, but its source code has hundreds of files, literally open a file to see thousands of lines of code, but also interspersed with a variety of conditional compilation, do not know how to look from ah.

Months passed, and then one day I came across a video about how to make a 3D printer by yourself. I opened it up and found it was pretty detailed. I downloaded the link and, boy, there was not just an assembly drawing, there was a BOM, and the BOM even included a link to buy each part and a reference price to prevent dishonest people from raising prices at will. Suddenly, I felt this thing was feasible, so I came up with the idea of DIY a 3D printer. He ordered a bunch of parts and waited a long time when he finally arrived, only to find that there was no suitable screwdriver when he bought the screws, so he ordered again and waited for the screwdriver to arrive. Bought the motherboard but found that the connection also need plastic shell terminal and crimping pliers, this wait is several days. So it took me a full two weeks to build my first DIY printer, the Big Fish I3, designed by Big Fish.

After assembling and tuning the machine, I had two working 3D printers. I actually prefer this DIY machine to the one I bought for over 2000. Because while the DIY one is a bit messy, time-consuming and laborious, I know exactly what to do if it breaks, and the printing accuracy is as good as the first. Of course, I am not saying that the previous machine (Anycubic Vyper) is not good. In fact, on the contrary, I think Anycubic Vyper not only performs well but also looks good. In fact, Big Fish has launched prints of 3 structures, respectively i3 CoreXY and UM. I chose the i3 structure largely because I already had a good printer with the i3 structure, so I could use it as a benchmark. Yes, Anycubic Vyper defines what I think a complete and refined printer looks like — it starts printing in 30 minutes, and has a nice looking and user-friendly interface that makes a 3D printer no longer a professional tool for professionals, but a home appliance for ordinary people. My goal, of course, is to understand how a 3D printer works, so these sophisticated tools can only be used as reference.

Now I have a basic understanding of the mechanics of a 3D printer. More importantly, I began to believe that I might be able to figure out how 3D printers work, too. So I decided to start trying to write my own 3D printer firmware. This part, like the soul of a 3D printer, is naturally more difficult to understand. Fortunately, after spending half a month staring at the screen every morning trying to figure out what was wrong with my code, only to fall asleep in despair before going to bed, I was able to print out a test model that was as good as normal. Also have this article, after all if can’t print the actual normal model, then I how qualified to write such articles.

The development environment

  • Development framework

    • Arduino
  • Main control chip

    • AVR mega2560
  • The main board

    • MKS GENL V2.1
  • Motor drive

    • X TMC2008
    • Y TMC2008
    • Z A4988
    • E TMC2225
  • display

    • Not implemented yet, through the serial port interaction
  • The fuselage

    • The big fish i3

G code parsing

The goal of this section is to implement the Gcode:: Parse method that converts G1 x2.4y5.6 of serial port input into a Gcode object

gcode.cmdtype = 'G';
gcode.cmdnum = 1;
gcode.x = 2.4;
gcode.y = 5.6;
Copy the code

The G code format I refer to is Marlin. This part is relatively simple, so I will skip it. The specific implementation can be seen in gcode/gcode.cpp. Finish to proceed to the next section.

The temperature control

The goal of this section is that the hot end of the SERIAL port input M104 S100 starts to heat and remains at 100 ° C after reaching 100 ° C.

Temperature control using PID controller, specifically to create a hotend object, it will have the following functions:

  • hotend.setTargetTemp(200)Set the target temperature at 200℃
  • hotend.readTemp()Read current temperature
  • hotend.update()To update MOS tube switching time

Hotend. Update () is executed once every 200ms. (The timer is initialized in Heater::init)

Vox Heater is implemented in module/ Vox vox. CPP, and interrupt service function is implemented in main.cpp

Here we mainly need to talk about the meaning of several parameters of PID controller (although their name sounds very complicated, but in fact they are just simple addition, subtraction, multiplication and division):

  • Controller output value

    • A number ranging from 0 to 255. 125 indicates that the heater power is set to 50%
  • Error

    • If the current temperature is 150℃ and the target temperature is 200℃, the deviation is 50
  • Proportion ratio

    p = kp * err;
    Copy the code
    • Suppose the current temperature is 150℃, the target temperature is 200℃,kpA value of 1.0, it isP item=50. Set the heater power as (50/255)=20%
    • And with that, you can control the temperature. But only this term may not be able to be added at 170℃, because the heater power is only 12% at this time, and the heat emitted by the heater into the air is the same power. This phenomenon is calledThe steady state error.
  • Integration points

    pidIntegral += err;
    i = ki * pidIntegral;
    Copy the code
    • I studyCan solve onlyP itemWhen theThe steady state error. Supposeki0.5, so when you add it to 170℃, the temperature can’t go up,pidIntegralIt increases by 30 per 200ms,I studyThis increases by 15 every 200ms and the heater power increases by (15/255)=6% every 200ms, so over time the temperature will naturally rise.
  • Differentiation of differential

    d = kd * (err - pidPrevErr);
    Copy the code
    • You might say, well, that’s my way of saying itP itemandI studyYou can control the temperature. Indeed, if you find oneP itemandI studyIf you can control the temperature well, that’s perfectly finekiBut if we want to keep the temperature from changing too fast, we can try addingD item.Since the target temperature is assumed to be 200℃,kdIf the temperature in the previous period was 170℃ and the temperature in the current period was 190℃, thenD itemIf the temperature in the previous period was 170 degrees Celsius, and the temperature in this period is 170 degrees Celsius, thenD itemIt’s 0, so to speakD itemThis guy isHate to changeThis is useful to prevent the temperature from falling too fast once it reaches the target temperature, as mentioned above,I studyIt takes “some time “,P itemAnd languish near the target temperature.

Motor control

The goal of this section is to achieve the positive and negative rotation of the stepper motor and achieve the G28 return to zero instruction

A4988

We will use the MODULE A4988 to control the stepper motor. The schematic diagram of A4988 is given below

  1. VMOT

    For 8V ~ 35V DC power supply, a 100uF capacitor needs to be placed between VMOT and GND to quickly respond to the power demand of the motor.

  2. 1A 1B

    Connect the first coil

  3. 2A 2B

    Connect the second coil

  4. VDD

    Answer the MCU power supply

  5. DIR

    Direction control pin, connected with MCU output, high and low level respectively represent a rotation direction

  6. STEP

    A square wave motor moves once. If the step subdivision is set to 1, the motor moves one step at a time. A step is 1.8°, and 200 steps can make a revolution

  7. MS1 MS2 MS3

    Step can be subdivided into up to 16 movements

8. ENABLE

When the low level module is connected, the module shuts down when the high level is connected, and the module works when the air is suspended.

  1. SLEEP

    Low level is connected to the motor power, by hand can be free rotation. The motor works when the high level is connected.

  2. RESET

    Default suspension. Reset module when low power is received. If you do not intend to control this pin, you should connect it to the SLEEP pin to set it to high.

Therefore, there are altogether 4 steps to use A4988 to control the motor, which is specifically realized in Module /Stepper. CPP

  1. Make sure you don’t install it upside down, the module will burn up.
  2. Set up theenablePin forLow levelTo activate the module
  3. Set up thedirPin to set direction
  4. tostepThe pins emit pulses to request motor movement
Axis steps

Now we know how to control the motor by A4988, but how far (mm) does the print head go when the motor turns one step?

  • Synchronous wheel and belt

    Take 2GT, 20-tooth synchronous wheel as an example. 2GT means that a belt with one tooth moves 2mm, then if the synchronous wheel has 20 teeth, turn one belt and move 40mm. If we use 16 subdivision motor drive, then a step motor circle is 3200 steps.

    Axis steps = 3200steps / 40mm = 80steps/mmCopy the code

    So if we use the structure of I3 and want the print head to advance 10mm in the positive direction of the x axis, then we need MCU to send 3200 * 10 = 32000 pulses to A4988.

  • screw

    Take a screw with a pitch of 2mm and lead of 8mm as an example. The lead means the straight-line distance traveled by the screw in one revolution. so

    Axis steps = 3200steps / 8mm = 400steps/mmCopy the code

    So if we use the structure of i3 and want the print head to advance 10mm in the positive direction of the Z axis, then we need MCU to send 3200 * 400 = 1,280,000 pulses to A4988

G28 zero

If you want to return to zero, in addition to the need to understand how to drive the motor, but also need to understand the principle of the limit switch

Limit switch has three pins which are normally open, normally closed and common. Accordingly, there are two modes of operationNormally openandNormally closed.Here we chooseNormally closed. Thus, the judgment can be realized by reading the level of MCU pinmodule/Endstop.cpp

Limit switch status Circuit on and off MCU pin level
Not trigger tong low
The trigger broken high

Path planning and execution

The goal of this section is that the serial port input G1 F1000 X6 Y3 hot end will arrive at the specified coordinate point.

Forward method

Assuming that our starting point is (0,0), then to go to (6, 3) we need to require the X motor to take (6 X 80) steps and the Y motor to take (3 X 80) steps. Of course, we can ask the X motor to go first and the Y motor to go after, and we can also reach the destination, but there is a considerable gap between the drawn line and the ideal line segment. Or we could draw the ideal segment first, and then draw lines around it.

But how is this to be done? This problem had been thought out by our predecessors, and they gave it a nameBresenham algorithmSpecifically, since it takes 480 steps in the X direction and 240 in the Y direction, that equals 480 steps in total, one step forward in the X direction and two steps forward in the Y direction. Each of these 480 movement events is called onestep eventThe total number is calledstep event countAnd its value is the larger value of X and Y.

// module/Planner.cpp - planBufferLine
block.stepEventCount = getMax(block.steps);

// main.cpp - motion control isr
motorX.deltaError = -(curBlock->stepEventCount / 2);
motorY.deltaError = motorX.deltaError;

motorX.deltaError += curBlock->steps.x;
if (motorX.deltaError > 0) {
    motorX.moveOneStep(a); motorX.deltaError -= curBlock->stepEventCount; } motorY.deltaError += curBlock->steps.y;if (motorY.deltaError > 0) {
    motorY.moveOneStep(a); motorY.posInSteps += curBlock->dir.y; motorY.deltaError -= curBlock->stepEventCount; }Copy the code

Note the implementation:

Do not use floating point numbers to count steps, as this will result in lost steps

Speed control

Use the timer interrupt time to control the print head forward speed.

For example, if we want the speed to be 1000steps/s, the timer would need to be generated every 1ms with a step event in the interrupt service function.

If we need to change the speed, we can set the counter value that triggers the interrupt in the interrupt service function. But we can set it to a constant speed for now.

Multiple motion command

Above, we realized how to execute a G1 instruction. What about all those instructions?

We can put an object in a queue that contains how many steps each motor is moving in that direction. Pull it out of the queue as needed.

Speed of cohesion

The goal of this section is to calculate the joining speed of two segments of motion, and then calculate when each segment accelerates and decelerates.

In fact, do the above steps, set the speed to uniform, the printer will work. But we can still change the speed of the printer to increase the printing speed.

Trapezoidal acceleration

As mentioned above, we can change the speed by changing the interruption time. Then there is the question: when to speed up, when to slow down?

Specifically, divide a block into accelerated, uniform and decelerated segments and calculate their lengths. The calculation is not complicated, as shown in the figure below. Note that if the current block length is very short, the acceleration graph will change from trapezoid to triangle.

Convergence speed

In order not to allow the speed and coherence between each block. We need to calculate the entry and exit speeds of each block. The estimation method is given below. It should be noted that the arc in the figure is only used to estimate the connection speed, and the actual path of the print head will not pass through this arc.

Afterword.

I didn’t like traveling before, because I thought it was just taking pictures in a different background. I like it now because my definition of travel has changed. I now define it as a deep exploration of one thing, and understanding how a 3D printer works is one of them.