Pages Navigation Menu

The software driving your 3d printer

Flash ad ID:23

Repetier-Firmware Documentation



First you need to get and install the development software. Don‘t worry, it is easy and you won‘t need special programming skills. Get your version of the Arduino IDE from . The software is available for WIndows, Linux and Mac. Follow the instruction on the Arduino site. For SD card support you will need Arduino 1.0 or higher.

The IDE contains only the officially supported board driver. If your board is not included, you need to install the missing device files. Not included are files for Gen 6, Sanguinololu, Gen7, Teensylu and Printrboard.

The next step is driver installation. The boards all use a serial protocol. Which is fine if your printer had a serial port. The designer of the Arduino knew this problem and have added a usb->serial converter on board. That is the reason, you need to install the usb driver used on the board. Some board/OS combinations don‘t need a special driver. If you are a Windows user – I didn‘t mean you.

To understand the IDE, you should now download the latest version of Repetier-Firmware.

It is not necessary to clone the repository. All you need is to download the contents as a ZIP file. Download the file and unpack the contents. Start the IDE and go to File->Open and select the file „Repetier.pde“ in the repetier subdirectory.

Before you can compile and upload the firmware, you need to select the board and port. You do this in the Tools menu. Start with your board. The port can only be selected, if your printer is online and connected.

For a first successful upload, follow the next steps:

  • Open the register tab named „Configuration.h“
  • Search the line „#define MOTHERBOARD“ and change the number behind to match your board.
  • Near the bottom you see a line „#define BAUDRATE 250000“. Change the baud rate to match your preferences or leave it.
  • Make sure the printer is connected and port and board type are set correctly.
  • Press the upload button. That is the button with the arrow to the right.
  • After a while you see the length of the compiled firmware file and the upload starts. On most boards you will see a led starting to flicker. After it stops flickering, the upload is verified and then you see the message „Upload done“ in the IDE.

Congratulations! You just compiled and uploaded your first firmware. You can start your host software and connect to the board with the set baud rate. Don‘t try to print now. You haven‘t set up everything needed. But you can already ask firmware name with „M115“ or move the printer head a bit (no long distance before you set up the correct steps per mm for your axis).

Common errors

  • If the MOTHERBOARD setting does not match your board settings, you will get a corresponding error message.
  • If your host is still connected to the board, you can not update a new firmware.
  • Sometimes the uploader fails to reset the board to start the bootloader. If you see the firmware is compiled and the led doesn‘t start flashing within 5 seconds, press the reset button on the board. Often this helps.
  • Sometimes you will get a fsync error message from the uploader. Unplug the printer and reconnect it. If it doesn‘t go away reboot your computer.

General configuration

In general you will only need to update two configuration files. The main configuration is „Configuration.h“ which is handled in this chapter. If you have a LCD display and optionally some keys, you also need to change the „uiconfig.h“ file if it is not supported by the firmware directly, which is handled in the next Chapter. The default is no LCD and no keys. If you have an unknown board or changed the usage of some pins, you need to update pins.h.

When you open the „Configuration.h“ file, you see a lot of comments and some values to change. These configurations are all done with preprocessor commands.

Short introduction into preprocessor directives

If you don‘t know what a preprocessor is or does, you should read this section carefully. I will explain everything you need to know for your configuration. Experienced programmer can skip this section.

The target of your configuration is to write a firmware that works perfectly with your printer. Viewing the RepRap webpage, you see man different kinds of printer using different boards and different sensors and setups. To create one firmware that works with all variations, it needs to be very flexible and to use data defining your special setup. To do this the preprocessor is used. It is a simple parser, that runs over the code before the real compilation starts. With the help of the preprocessor you can enable or disable parts of the code, replace contents by values defined in the preprocessor and do some error checking.

All preprocessor commands can be recognized by the # char at the beginning of the command. The most important commands is #define. It defines a symbol, which is replaced by it‘s content everywhere it is found later on in the code.


#define MY_NUMBER 8
#define SQUARED(a) (a)*(a)

The above code will be converted into the following:


Things to notice:

  • The define name is written in capital letters. This is not needed, but a helpful convention. Throughout the complete code, you will recognize the preprocessor macros at the capital characters.
  • Defines can have parameters.
  • Defines don‘t need a replacement values – they can be empty.
  • Macros can be passed as parameter to other macros.
  • If you have a long macro and you want to split it over several lines, you have to end the line with a backslash „\“ character. No more spaces after that backslash are allowed.

The firmware uses two different methods to compile code on special conditions. For one method you need to define a special value, say 0 for don‘t compile and 1 for compile. The other method is the pure existence of the define. In the configuration you see sometimes an commented define. If you remove the comment marks // the define is active and it‘s code is used or not. See the following example, how this works:

#define PRINTTYPE 1
#define DOIT
//#define DOITTOO
print("Type is 1");
print("Type is 2"); // Not called, because PRINTTYPE is 1
#ifdef DOIT
print("Doit defined");
print("Doit not defined"); // Not called
#ifndef DOITTOO
print("I'm also called.");


The EEPROM trap

I already explained how handy it is to use the EEPROM feature. It is important, that you understand how it works, so you get what you think you said. In your „Configuration.h“ you have the following line:

#define EEPROM_MODE 1

A value of 0 would disable the EEPROM usage. Any other value from 1 to 255 enables it and determents if the values from the configuration file are copied to the EEPROM at the first start, or if the old values are kept. The trick is quite simple. The first byte in EEPROM is compared with the EEPROM_MODE value. If it has a different value, the values in your „Configuration.h“ are copied to EEPROM and byte 0 is set to the mode. After the next startup, the firmware sees the value is the same and will use the values already stored in EEPROM,

A correct initialization is important for a good function. If you have used an other software, that also writes to the EEPROM, your data gets corrupted and you should make sure, the values are reinitialized. From version 0.80 onwards the firmware stores a checksum, so most corruptions are detected automatically.

If you have followed the first installation example, you have already written values to your EEPROM. It is a good idea to change the EEPROM_MODE to 2 now, so you overwrite it with the configuration you will now define.

From version 0.80 onwards you can overwrite the EEPROM values with the values from Configuration.h using M502.

Modifying EEPROM values

The easiest way to change the EEPROM values it with Repetier-Host. It has a form for editing the stored values, so you don‘t need to bother with the correct commands.

For a manual change send “M205″ to your board and you will get a list with all parameters with position, type and value. The output will look like this:

EPR:2 75 76800 Baudrate
EPR:2 79 0 Max. inactive time [ms,0=off]
EPR:2 83 60000 Stop stepper afer inactivity [ms,0=off]
EPR:3 3 40.00 X-axis steps per mm
EPR:3 7 40.00 Y-axis steps per mm
EPR:3 11 3333.59 Z-axis steps per mm
EPR:3 15 20000.00 X-axis max. feedrate [mm/min]
EPR:3 19 20000.00 Y-axis max. feedrate [mm/min]
EPR:3 23 2.00 Z-axis max. feedrate [mm/min]
EPR:3 27 1500.00 X-axis homing feedrate [mm/min]
EPR:3 31 1500.00 Y-axis homing feedrate [mm/min]
EPR:3 35 100.00 Z-axis homing feedrate [mm/min]
EPR:3 39 20.00 X-axis start speed [mm/s]
EPR:3 43 20.00 Y-axis start speed [mm/s]
EPR:3 47 1.00 Z-axis start speed [mm/s]
EPR:3 51 750.00 X-axis acceleration [mm/s^2]
EPR:3 55 750.00 Y-axis acceleration [mm/s^2]
EPR:3 59 50.00 Z-axis acceleration [mm/s^2]
EPR:3 63 750.00 X-axis travel acceleration [mm/s^2]
EPR:3 67 750.00 Y-axis travel acceleration [mm/s^2]
EPR:3 71 50.00 Z-axis travel acceleration [mm/s^2]
EPR:3 150 373.00 Extr. steps per mm
EPR:3 154 1200.00 Extr. max. feedrate [mm/min]
EPR:3 158 10.00 Extr. start feedrate [mm/s]
EPR:3 162 10000.00 Extr. acceleration [mm/s^2]
EPR:0 166 1 Heat manager [0-1]
EPR:0 167 130 PID drive max
EPR:2 168 300 PID P-gain [*0.01]
EPR:2 172 2 PID I-gain [*0.01]
EPR:2 176 2000 PID D-gain [*0.01]
EPR:0 180 200 PID max value [0-255]
EPR:2 181 0 X-offset [steps]
EPR:2 185 0 Y-offset [steps]
EPR:2 189 40 Temp. stabilize time [s]

The first value is the data type (0=byte, 1=16 bit int,2=32 bit int,3 = float). The second parameter is the position in EEPROM, the value is stored. The third parameter is the current value. The rest of the line is a short description of the parameter.

To change one of these parameters, send

M206 T<type> P<position> S<new_value>

for types 0-2 and for type 3 use

M206 T<type> P<position> X<new_value>

Type and position must match the values returned by M205, otherwise you will overwrite some other data with undeterminable results.

Your initial configuration

Now you should start to work yourself through the „Configuration.h“ and change the settings to match your setup. There are many comments in that file explaining what value are allowed and what is meant. I will not go into every detail. The following sections will give some useful help and background information.

Steps per mm

Your printer uses stepper motors to move the extruder and for the extrusion it self. Depending on your configuration, you need x steps to move or extrude 1 mm. That is the value you need to enter. With some math you can get the values very easy. Do the example computations with your hardware settings and you are done.

StepsPerTurn = 200 // Most stepper motors have 1.8 Degree per step (some 0.9)
BeltDistance = 5mm // Ditance between repeating grooves. T5 belt => 5mm
GroovesInPulley = 8 // 8-10 are common values
Substepping = 16 // 16 Substeps for a full step needed
StepsPerMM = StepsPerTurn*Substepping/(BeldDistance*Substepping)
           = 200*16/(5*8) = 80

Temperature measurement

Before you can control the temperature, you need to measure it. The most common method used in the RepRap community is to use a NTC thermistor. With the help of of the circuit shown below, the AVR can measure a voltage, which depends on the used resistors and the temperature at the thermistor.

So how does it work? For a long and good description read nopheads excellent article ( The short version is, the NTC changes its resistance. Using a NTC means, with increasing temperature the resistance drops. This causes the measured voltage to change. With the full circuit, we end with the formula:

VMeasured = VRef*RS / (RS+R2)

If you have no resistor R1, RS = R. If you have, then

RS = R * R1 / (R+R1)

After knowing how to convert a temperature into a voltage, how do we get this into the firmware? The current Arduino generation uses AVR controller with a resolution of 10 bit. The voltage is converted into a number between 0 for ground and 1023 for VRef, which is normally 5V. The new XMega AVR controller have a resolution of 12 bit, resulting in values from 0 to 4095. To be ready for the future, the firmware adds 4 readings for a temperature calculation, resulting in a range from 0 to 4092. From this value, the firmware must compute the temperature at the thermistor. So far, so good. Unfortunately, the voltage-temperature-curve is nonlinear and differs for every thermistor type. Even different 100K thermistors have different curves. As a solution, the firmware uses a lookup table from which it interpolates temperatures between given values.

For a better understanding, lets have a look at one of these tables:

 {441*4,120*8},{513*4,110*8},{588*4,100*8},{734*4,80*8},{856*4,60*8},{938*4,40*8},{986*4,20*8},{1008*4,0*8},{1018*4,-20*8} }

For those with little C experience: The define must be in one line, which isn’t very readable. So to break it into different lines, append a backslash at the end of the line, to indicate that the line continues in the following line.

This lookup table has 28 reference values. Make sure the correct number is set in you configuration. For this table, I set


The table here contains 28 pairs of {adc, temperature*8} with the adc reading in range 0-4093 and temperature values multiplied with 8 as integer. The pairs must be ordered with increasing adc values!

What you see is the lookup table for an EPCOS G550 thermistor. The table consists of two columns. The first is the voltage reading and the second is the temperature. In the table, you see that the readings are multiplied with 4 and the temperatures with 8. I’ve taken this format, because most firmwares use a reading range from 0-1023 and full integer values for temperatures. Repetier-Firmware uses a higher resolution for input and temperature and these factors convert old tables you may have into the needed value range for Repetier-Firmware. If you don’t have a matching table, you have to compute one.

Looking into the datasheet gives characteristic curve 8404 for this thermistor. A look into the table shows temperatures and a factor RT/R25. Knowing R25 is 100K, we can compute the resistance for every temperature. Lets look at 100°C. We get a factor 0.063688, so R100 = 100000*0.063688 = 6368.8. In this example I take R1 not present and R2 = 4,7K. U100 = 4093*6368.8/(6368.8+4700) = 2355 = 4*588.76

Compute the values and enter them into one of the user definable thermistor lookup tables in Configuration.h. The order matters – start with the highest temperature. You can leave the first value for safety.

Controlling temperature

Knowing the temperature, we can start controlling the heater. The firmware currently supports two methods.

Bang-Bang control

This is the method used for a heated bed and for the extruder, if you set heat manager to 0. The principle is very simple. If the measured temperature is below the target temperature, the heater is set at full power. If the temperature rises above the target temperature, the heater is turned off.

Pros: Simple Cons: Temperature oscillates around the target temperature. For the heated bed, this is no real problem. If you are using PLA this is no big issue. With ABS you may want a more precise control.

PID control

For a better controlled temperature, the firmware uses a PID controller. This requires an output with PWM using a unused timer. Currently only RAMPS 1.0 doesn’t have a free timer for PID control. PID control is only implemented for extruder. For a better overview, lets have a look at the parameter used:

/** \brief The maximum value, I-gain can contribute to the output.
A good value is slightly higher then the output needed for your temperature.
Values for starts:
130 => PLA for temperatures from 170-180°C
180 => ABS for temperatures around 240°C
The precise values may differ for different nozzle/resistor combination. 
 Overridden if EEPROM activated.
/** \brief lower value for integral part
The I state should converge to the exact heater output needed for the target temperature.
To prevent a long deviation from the target zone, this value limits the lower value.
A good start is 30 lower then the optimal value. You need to leave room for cooling.
 Overridden if EEPROM activated.
/** P-gain. Overridden if EEPROM activated. */
#define EXT0_PID_P 24
/** I-gain. Overridden if EEPROM activated.
#define EXT0_PID_I 0.88
/** Dgain. Overridden if EEPROM activated.*/
#define EXT0_PID_D 80
// maximum time the heater is can be switched on. Max = 255. Overridden if EEPROM activated.
#define EXT0_PID_MAX 255

I know, quite a number of factors, but don’t worry. It’s not that complicated if you understand, what the parameter are used for.

The first one you should look at is PID_MAX. It’s the maximum PWM setting for your output. Normally, the heating resistor is selected, that a maximum value of 255 is allowed, meaning the full voltage (normally 12V) is send to the resistor. The lost energy at the resistor is U2/R. If you increase your voltage above the designed voltage, you may blow it with full settings. Reduce it in this case.

At the start, the controller behaves like the Bang-Bang controller, except that it uses PID_MAX instead of full power. Only if the current temperature is in a range of +/-10°C from the target temperature the real PID control starts. For the output, three terms P, I and D are computed and added to get the output value. The result is clipped to the range 0..PID_MAX


The P-Term adds a value proportional to the temperature error.

P = (TTarget-TCurrent)*P_GAIN

The closer the target temperature is reached, the lower the term gets. It will always oscillate around a value some degrees below the target temperature if left alone.


The I-Term is the most important one. The I-Term tries to find the perfect output for your temperature. It does this by incrementing/decrementing the output slowly. The speed is defined by the I_GAIN parameter. You can help a lot, if you limit the range of possible values to a known range INTEGRAL_DRIVE_MIN .. INTEGRAL_DRIVE_MAX. The min value should be at least 0 and the max not exceed 255. If you don’t know what works for you, use these extreme values and watch the output with the command M203 S0. When you that the temperature stabilizes, take the mean value and add/sub 20. If you like to change temperatures, set the limits, so all possible ranges are enclosed with a safety factor.

If your I_GAIN is set to a good value, you will see that the oscillation gets smaller with time. Disturbances like different printing speed or blowing at the nozzle may increase the error again.


The D-Term is the damping factor. With a good damping factor, your oscillations will slow down much faster and you get a much more stable system. Don’t by show using more then 100%. The default is already 500%.

Finding proper PID values is difficult for the unexperienced. To overcome this, the firmware has a autotune function to find good values. Disable the extruder and wait until it is more or less cold. Then start autotune with

M303 P0 S180
This assumes you want to find the PID values for your first extruder and your typical target temperature will be 180°C. For your second extruder you would use P1 and for the heated bed use the number of extruders as P-value.


This option only tells, when and how to scale down to DRIVE_MAX. If set to 0, the addition of the PID-Terms is clamped to 0..DRIVE_MAX. If you set this to 1, the PID Term gets clamped to 0..255 and is then scaled to 0..DRIVE_MAX.

What’s the difference? If you have DRIVE_MAX=255 there is no difference. If you have found your perfect values for 12V and DRIV_MAX=255 and now want’s to use 18V, you have to reduce DRIVE_MAX to DRIVE_MAX_OLD*(12^2/18^2)=113 to protected your resistor. If you want to keep your found factors, set DRIVE_MAX to 133 and SCALE_PID_TO_MAX 1. If you leave it 0, the found terms are to high and don’t work any more.


Jerk is what makes your printer shake. It is a speed difference between two moves, which can be reached without acceleration. So why do you want jerk and what does it influence? The first thing it influences is the starting speed. It is 50% of the allowed jerk. So if you have a jerk of 20, the first move will start with 10mm/s. The other thing jerk controls is the join speed for consecutive segments. In the figure above you see two examples. The jerk is the difference of the two speeds. Example 1 shows a jerk, that is higher then allowed. In this case, the path planner will reduce the speed to match exactly the maximum allowed speed. Example 2 has a lower directional change, so the jerk is within allowed limits and the planner allows a full speed move through the edge. The jerk is set these two values:

#define MAX_JERK 20.0
#define MAX_ZJERK 0.3

MAX_JERK is for x/y axis moves and MAX_ZJERK for moves in Z direction.

You want high jerk values, because

  • printing time is reduced.
  • print shows less blobs.

You want low jerk values, because

  • it causes less mechanical stress to your printer.
  • moves are smoother.
  • filament has better adhesion at directional changes.
  • reduces printer noise.
  • you loose steps with higher values.

You see, it is balance between your personal priorities. The only simple thing is z-jerk, which has nearly no influence. It only reduces the time for z-moves, but has no effect on quality.

Path planning

Path planning makes your printer moves more smooth. Have a look at the above picture. It shows a print of three lines. Without path planning, the printer needs to follow the blue path. For each segment it will accelerate to the commanded feed rate and back to the maximum end speed allowed. The path planner looks for previous moves, which aren‘t executed now and tries to remove the deceleration/acceleration between line joints, resulting in the much smoother red line. For each line joint, the maximum allowed jerk is computed and speed is reduced if needed to reduce the jerk. In most cases this is still much faster then the start/stop speed you would have otherwise. In circles you will most likely have no speed reduction at all. The only bad thing about path planning is, that it needs computation time. For each new line segment the algorithm needs to update older entries. For normal moves, this is no big deal and is very fast. Only if you have many very short moves, the update time becomes dominant and the firmware has to slow down the print. The behavior is influenced by the following configuration parameter:

MOVE_CACHE_SIZE (default 16)

That is the size of the buffer for currently processed segment and following moves. If you have 8kb RAM you can increase this to 24 if you want. It could make print smoother if they have many small lines.

MOVE_CACHE_LOW (default 10)

The path planner has some tricks to prevent empty buffers. One is to make a minimum move time per segment. If the buffer has only MOVE_CACHE_LOW or less segments, each segment is slowed down if would be shorter otherwise. For typical prints the buffer always has MOVE_CACHE_SIZE or MOVE_CACHE_SIZE-1 moves stored and normal moves are long enough, that no speed reduction is needed anyway. This is only effective for very short moves. Higher values can increase computation cost in extreme situations.

LOW_TICKS_PER_MOVE (default 250000)

The minimum time in processor ticks, each segment must need if the cache is low. The default value means, there will be still 40 segments printed per second.


Trajectory smoothing

The firmware uses the bresenham algorithm for the computations of the x, y, z and e axis. It takes the axis with the most steps needed and moves over the steps of this axis. At these steps it looks if other axis need also a step. What happens is, that the timing of the primary axis is perfect, while the dependent axises are only updated at the discrete points, not at the best time. This gives a little jitter to the dependent axis. To reduce this effect, the firmware can do half steps on the primary axis. The price you pay is double computation cost for the stepper update computation. For safety, this behavior is only enabled, if the shortest time between two full steps is larger then MAX_HALFSTEP_INTERVAL ticks (default1999). This allows smoothing with a frequency of 8000 hertz. If you have 80steps/mm you can print with up to 100mm/s and still benefit from the smoothing effect.

Speed settings

Always look at the unit of measurement. Feed rates are always in mm/s!

First you should think about your maximum speed your printer can handle.  Most printer will be able to handle 100mm/s (except z axis which is much slower for most printer types). 200mm/s is a solid speed most printer can handle. Fast printers go up to 500mm/s.  You should test these values when you installed the firmware. Find the speed where no stepper stalls and reduce this by 10-20% for safety. The last thing you want are lost steps during print, because your limit was too high. Your motor current has influence on your speed, too. Be aware that high currents heat up the motors and drivers which can also lead to lost steps!

#define MAX_FEEDRATE_X 200
#define MAX_FEEDRATE_Y 200
#define MAX_FEEDRATE_Z 40
Next comes the homing feed rate. This should be much lower then your maximum. The printer needs to stop immediately, when the end stop is triggered. So take values, which allow a stop without deceleration.


Now we come to the acceleration. The firmware distinguishes between travel and printing moves. Travel moves have no influence on print quality, so you can use higher values here. For x- and y-axis 500 mm/s2 is slow, 1000mm/s2 a moderate value for smooth prints and 3000 mm/s2 is good for quick prints.

Stepper timings

The default values for stepper timings work perfectly with the Allegro stepper driver chips used on most RepRaps. So only change them if you think you have a different driver which needs slower timings.

The step signal is normally kept high for around 2µs, depending on the situation a bit longer. You can increase this time with


The unit is µs.

Now we come to the tricky part allowing high step rates of 40000 hertz with this little AVR microcontroller. The real limit for precise positioned stepper pulses lies around 16000 Hz. With this speed over 80% of the computation time is spend in the stepper routine and leaves not much room for other tasks. The trick is to double or quadruple the number of step signals in one computation. The frequency, where this starts is


If the frequency is higher, then this value the firmware will double the steps for frequencies of 10000-20000 Hz and quadruple steps above 20000 Hz. If your printer is no real CNC, it will have no problems with this. Think of it as reducing 1/16th micro stepping to 1/8th or 1/4th micro stepping.

If double/quadruple stepping is active, the consecutive steps are delayed by

#define DOUBLE_STEP_DELAY 1 // time in us

Extruder configuration

Most parts of the extruder configuration are already explained. In this chapter you will learn all about the other parameter not mentioned yet. Lets go through the basic per extruder settings first.

#define NUM_EXTRUDER 1

Most of you will only have and use one extruder. The firmware is designed to support 2 or 3 extruder. This feature is not tested at all, so no one can tell if it would work. I‘m working on a printer with double extruder to check the functionality. If you have one, try it and I will help you with possible problems.

If you have a second extruder, you need to copy the EXT0_  definitions and rename them to EXT1_ for the configuration of the second extruder.

#define EXT0_X_OFFSET 0
#define EXT0_Y_OFFSET 0

Printing commands are based on one position for all tools. Switching the extruder needs to move the head, so the second extruder is exactly at the position of the first extruder. These coordinates are the difference to the position of the first extruder.

#define EXT0_STEPS_PER_MM 373

How many steps does the motor need to move the filament 1 mm. This is the number for the filament going in, not out!


What temperature sensor are you using in the extruder. The configuration file lists possible values and meanings.


This parameter is tricky and often causes wrong configurations. For historical reasons it is named PIN but it IS NOT A PIN NUMBER. It is the position in an array of analog input sources. In this array, the real pin number is stored. In 99.9% 0 is the correct answer here.


Which pin enables the heater block. It works with any pin. PWM capability is not required to use PID on an output.


Which pin moves the Stepper one step further.


Which pin determines the turning direction of the extruder.

#define EXT0_INVERSE false

If your extruder turns in the wrong direction, change the value into true.


Pin to activate/deactivate your extruder stepper motor.

// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
#define EXT0_ENABLE_ON false

For inverting stepper enable pins (active low) use false, non Inverting (Active High) use true.

#define EXT0_MAX_FEEDRATE 1500

Maximum feed rate of your extruder in mm/min.


Starting feed rate in mm/s of your extruder. Normal feed rates are 12-20mm/s depending on motor strength, friction and extruder type. If your extruder stalls on retractions from the start, reduce this value.


Acceleration of your extruder in mm/s2.


Type of heat manager for this extruder.

  • 0 = Simply switch on/off if temperature is reached. Works always.
  • 1 = PID Temperature control. This method gives more stable results with a good PID parameter setting.

Wait x seconds, after reaching target temperature. Only used for M109.


The maximum value, I-gain can contribute to the output.

A good value is slightly higher then the output needed for your temperature.

Values for starters:

130 => PLA for temperatures from 170-180°C
180 => ABS for temperatures around 240°C

Depending in your heater these values can vary. If your printer can not hold the target temperature or does not reach it, increase this value!


Lower value for integral part. The I state should converge to the exact heater output needed for the target temperature. To prevent a long deviation from the target zone, this value limits the lower value. A good start is 30 lower then the optimal value. You need to leave room for cooling.

#define EXT0_PID_PGAIN   500

P-gain in 0.01 units.

#define EXT0_PID_IGAIN   1

I-gain in 0.001 units.

#define EXT0_PID_DGAIN 3000

D-gain in 0.01 units.

#define EXT0_PID_MAX 255

Maximum time the heater can be switched on. Max = 255. This works only with PID. The power dissipated by the heating resistor is U2/R. If you increase the voltage your resistor may get damaged if you still use full power.

#define EXT0_ADVANCE_K 0.0f
#define EXT0_ADVANCE_L 0.0f

Values to influence the advance algorithm. Check the advance algorithm chapter for more information. 0 disables the function.

 User interface configuration

It is possible to control all operations of the printer over a serial line. But if you want a stand alone printer or simple some additional way of input, you can use the user interface methods offered by the firmware.

The simplest addition is a single LCD, which shows some current data like extruder/bed temperature or z-level. If you want some methods of input, you can add keys. The minimum required is three signals. You can use a rotary encoder with push button function or three plain push buttons. The addition of a complete key matrix up to 4×4 buttons is also possible. For acoustic feedback, a piezo buzzer can be added.

The current implementation supports direct connection to IO pins of your Arduino or an indirect connection over I2C to a PCF8574 chip, where the display and keys/buzzer are connected. You need one chip for the display and one for the keys and buzzer. If you have the pins, use direct connection. It is much faster and less error prone. A rotary encoder over I2C works only with slow turns!

Hardware connection


The current firmware supports LCD display usinga HD44780 or compatible driver. This is a industrial standard that is found in nearly all alpha-numeric LCD displays. If you buy one, be careful about the voltage requirements. Some LCDs need negative voltage for contrast. If you don’t know how to get negative voltages avoid them. There are plenty of displays using only positive voltages. It’s best to put a 10k poti between 0 and 5V and connect the middle pin to V0. That way you can adjust the contrast any time. For the backlight a resistor is normally required. Read the specs for the required value. Some LCD have the resistor build in, so they can be powered with 5V directly. Now connect VSS, DB0, DB1, DB2, DB3 and LED- with GND and VDD with 5V. Connect RS, R/W, E, DB4, DB5, DB6 and DB7 to io pins of your Arduino or to the signal pins of your PCF8574 chip, if you are connecting the display over I2C. Then you are done! Make sure you know which pin is connected to which function for later configuration.


The easiest way is, to connected the keys via gnd to the io pin of your Arduino/PCF8574. It is always a good idea to add a 1K resistor in line, just in case the pin becomes an output to prevent a short. The internal pull-up will rise the signal to high, until a button is pushed and draws the line to ground.

You can also connect the keys via 5V, but you need a pull-down resistor on the io side for a defined signal.

If you have a key matrix you need up to 4 io pins for the driving rows and 1-4 pins for the receiving columns. The voltage on the rows gets changed between 0 and 5V to detect the active key. If you press 2 keys in the same column at the same time, a short will happen. To protect your cpu, you should add 1K resistors to each line.

Piezo Buzzer

If you want acoustic feedback, you can add a piezo buzzer. Get one that draw less then 20mA current. If you connect it directly to your AVR, connect GND – Buzzer – IO pin. If you use PCF8574 you have to connect it this way: 5V – buzzer – PCF8574 pin. Piezo elements have a plus and a minus contact, don’t run them the wrong way around!


All configurations of the user interface are done in uiconfig.h.


The firmware uses a very flexible concept for the user interface. The key behind all this is a flexible output command and assignable actions. So how does it work? Everywhere, where you can define some output you can include place holder for special values like current temperature or z-position. It doesn’t really matter for which function the output was meant, you can show the temperature in the x-position menu if you like. These placeholder always consist of three chars, beginning with a %. The following two letter determine the information shown.

List of placeholder

  • %ec : Current extruder temperature
  • %eb : Current heated bed temperature
  • %e0..9 : Temp. of extruder 0..9
  • %er : Extruder relative mode
  • %Ec : Target temperature of current extruder
  • %Eb : Target temperature of heated bed
  • %E0-9 : Target temperature of extruder 0..9
  • %os : Status message
  • %oe : Error message
  • %oB : Buffer length
  • %oc : Connection baudrate
  • %o0..9 : Output level extruder 0..9 is % including %sign.
  • %oC : Output level current extruder
  • %ob : Output level heated bed
  • %%% : The % char
  • %x0 : X position
  • %x1 : Y position
  • %x2 : Z position
  • %x3 : Current extruder position
  • %sx : State of x min endstop.
  • %sX : State of x max endstop.
  • %sy : State of y min endstop.
  • %sY : State of y max endstop.
  • %sz : State of z min endstop.
  • %sZ : State of z max endstop.
  • %do : Debug echo state.
  • %di : Debug info state.
  • %de : Debug error state.
  • %dd : Debug dry run state.
  • %O0 : OPS mode = 0
  • %O1 : OPS mode = 1
  • %O2 : OPS mode = 2
  • %Or : OPS retract distance
  • %Ob : OPS backslash distance
  • %Od : OPS min distance
  • %Oa : OPS move after
  • %ax : X acceleration during print moves
  • %ay : Y acceleration during print moves
  • %az : Z acceleration during print moves
  • %aX : X acceleration during travel moves
  • %aY : Y acceleration during travel moves
  • %aZ : Z acceleration during travel moves
  • %aj : Max. jerk
  • %aJ : Max. Z-jerk
  • %fx : Max. feedrate x direction
  • %fy : Max. feedrate y direction
  • %fz : Max. feedrate z direction
  • %fe : Max. feedrate current extruder
  • %fX : Homing feedrate x direction
  • %fY : Homing feedrate y direction
  • %fZ : Homing feedrate z direction
  • %Sx : Steps per mm x direction
  • %Sy : Steps per mm y direction
  • %Sz : Steps per mm z direction
  • %Se : Steps per mm current extruder
  • %is : Stepper inactive time in seconds
  • %ip : Max. inactive time in seconds
  • %X0..9 : Extruder selected marker
  • %Xi : PID I gain
  • %Xp : PID P gain
  • %Xd : PID D gain
  • %Xm : PID drive min
  • %XM : PID drive max
  • %XD : PID max
  • %Xw : Extruder watch period in seconds
  • %Xh : Extruder heat manager (BangBang/PID)
  • %Xa : Advance K value
  • %Xx : x offset in steps
  • %Xy : y offset in steps
  • %Xf : Extruder max. start feedrate
  • %XF : Extruder max. feedrate
  • %XA : Extruder max. acceleration

Notice: Some values are only available, if the matching functions are included. E.g. the PID values are only possible if you compiled with PID support.

The second key concept are actions. An action is defined by what happens if it is executed. One possible action is home x, so if it is executed, your extruder will move to x home position. It doesn’t matter what triggered that action. You can assign this to a key or it can be an action belonging to an menu entry.

Possible actions for keys and menu functions

  • UI_ACTION_NEXT : Next higher value/menu entry
  • UI_ACTION_PREVIOUS : Previous lower value/menu entry
  • UI_ACTION_X_UP : Move x axis 1 mm right
  • UI_ACTION_X_DOWN : Move X axis 1 mm left
  • UI_ACTION_Y_UP : Move Y axis 1 mm to front
  • UI_ACTION_Y_DOWN  : Move Y axis 1 mm back
  • UI_ACTION_Z_UP : Move Z axis 1 mm up
  • UI_ACTION_Z_DOWN : Move Z axis 1 mm down
  • UI_ACTION_EXTRUDER_UP : Extrude filament 1 mm
  • UI_ACTION_EXTRUDER_DOWN : Retract filament 1 mm
  • UI_ACTION_EXTRUDER_TEMP_UP : Increase extruder temperature 1 degree
  • UI_ACTION_EXTRUDER_TEMP_DOWN : Decrease extruder temperature 1 degree
  • UI_ACTION_HEATED_BED_UP : Increase bed temperature 1 degree
  • UI_ACTION_HEATED_BED_DOWN : Decrease bed temperature 1 degree
  • UI_ACTION_FAN_UP  : Increase fan speed 12.5%
  • UI_ACTION_FAN_DOWN  : Slow fan 12.5% down
  • UI_ACTION_DUMMY : Do nothing
  • UI_ACTION_BACK : Go one menu level higher
  • UI_ACTION_OK : Select entry or finish setting value
  • UI_ACTION_MENU_UP : Go one menu level higher
  • UI_ACTION_TOP_MENU : Go to the information menu
  • UI_ACTION_EMERGENCY_STOP : Stop printer, run endless loop
  • UI_ACTION_XPOSITION : Change x position with microstep resolution
  • UI_ACTION_YPOSITION : Change y position with microstep resolution
  • UI_ACTION_ZPOSITION : Change z position with microstep resolution
  • UI_ACTION_EPOSITION : Change extruder position with 1mm resolution
  • UI_ACTION_BED_TEMP : Change heated bed temperature
  • UI_ACTION_EXTRUDER_TEMP : Change extruder temperature
  • UI_ACTION_SD_DELETE : Delete file on sd card
  • UI_ACTION_SD_PRINT : Print file on sd card
  • UI_ACTION_SD_PAUSE : Pause/stop sd print
  • UI_ACTION_SD_CONTINUE : Continue sd print
  • UI_ACTION_SD_UNMOUNT : Unount sd card
  • UI_ACTION_SD_MOUNT : Mount sd card
  • UI_ACTION_XPOSITION_FAST : Change x position with 1mm steps
  • UI_ACTION_YPOSITION_FAST : Change x position with 1mm steps
  • UI_ACTION_ZPOSITION_FAST : Change x position with 1mm steps
  • UI_ACTION_HOME_ALL : Home all axis
  • UI_ACTION_HOME_X : Home x axis
  • UI_ACTION_HOME_Y : Home y axis
  • UI_ACTION_HOME_Z : Home z axis
  • UI_ACTION_SELECT_EXTRUDER1 : Make extruder 1 current extruder
  • UI_ACTION_OPS_RETRACTDISTANCE : Change OPS retractions distance
  • UI_ACTION_OPS_BACKSLASH : Change OPS backslash
  • UI_ACTION_OPS_MOVE_AFTER : Change OPS move after
  • UI_ACTION_OPS_MINDISTANCE : Change OPS min. distance
  • UI_ACTION_STORE_EEPROM : Store settings in EEPROM
  • UI_ACTION_LOAD_EEPROM : Load settings from EEPROM
  • UI_ACTION_PRINT_ACCEL_X : Change x acceleration during print
  • UI_ACTION_PRINT_ACCEL_Y : Change y acceleration during print
  • UI_ACTION_PRINT_ACCEL_Z : Change z acceleration during print
  • UI_ACTION_MOVE_ACCEL_X : Change x acceleration during moves
  • UI_ACTION_MOVE_ACCEL_Y : Change y acceleration during moves
  • UI_ACTION_MOVE_ACCEL_Z : Change z acceleration during moves
  • UI_ACTION_MAX_JERK : Change jerk value
  • UI_ACTION_MAX_ZJERK : Change z-jerk value
  • UI_ACTION_BAUDRATE : Change baudrate. Works only after storing to eeprom and reset!
  • UI_ACTION_HOMING_FEEDRATE_X : Change x homing feedrate
  • UI_ACTION_HOMING_FEEDRATE_Y : Change y homing feedrate
  • UI_ACTION_HOMING_FEEDRATE_Z : Change z homing feedrate
  • UI_ACTION_MAX_FEEDRATE_X : Change maximum x feedrate
  • UI_ACTION_MAX_FEEDRATE_Y : Change maximum y feedrate
  • UI_ACTION_MAX_FEEDRATE_Z : Change maximum z feedrate
  • UI_ACTION_STEPS_X : Change steps per mm in x direcion
  • UI_ACTION_STEPS_Y : Change steps per mm in y direcion
  • UI_ACTION_STEPS_Z : Change steps per mm in z direcion
  • UI_ACTION_FAN_OFF : Turn fan off
  • UI_ACTION_FAN_25 : Set fan to 25%
  • UI_ACTION_FAN_50 : Set fan to 50%
  • UI_ACTION_FAN_75 : Set fan to 75%
  • UI_ACTION_FAN_FULL : Set fan to 100%
  • UI_ACTION_FEEDRATE_MULTIPLY : Change feedrate multiplier
  • UI_ACTION_STEPPER_INACTIVE : Change stepper inactivity timeout
  • UI_ACTION_MAX_INACTIVE : Change max inactivity timeout
  • UI_ACTION_PID_PGAIN : Change P gain for PID of current extruder
  • UI_ACTION_PID_IGAIN : Change I gain for PID of current extruder
  • UI_ACTION_PID_DGAIN : Change D gain for PID of current extruder
  • UI_ACTION_DRIVE_MIN : Change drive min for PID of current extruder
  • UI_ACTION_DRIVE_MAX : Change drive max for PID of current extruder
  • UI_ACTION_X_OFFSET : Change x offset of current extruder
  • UI_ACTION_Y_OFFSET : Change y offset of current etxruder
  • UI_ACTION_EXTR_STEPS : Change steps per mm of current extruder
  • UI_ACTION_EXTR_ACCELERATION : Change extruder acceleration
  • UI_ACTION_EXTR_MAX_FEEDRATE : Change extruder maximum feedrate
  • UI_ACTION_EXTR_START_FEEDRATE : Change extruder start feedrate
  • UI_ACTION_EXTR_HEATMANAGER : Change etxruder heat manager
  • UI_ACTION_EXTR_WATCH_PERIOD : Change temperture stabalize time
  • UI_ACTION_PID_MAX : Change extruder pid max value
  • UI_ACTION_ADVANCE_K : Change advance K value
  • UI_ACTION_SET_ORIGIN : Set x,y and z origin to current position
  • UI_ACTION_DEBUG_ECHO : Enable/disable echo of received messages
  • UI_ACTION_DEBUG_INFO : Enable/disable info messages
  • UI_ACTION_DEBUG_ERROR : Enable/disable error reports
  • UI_ACTION_DEBUG_DRYRUN : Enable/disable dry run mode
  • UI_ACTION_PREHEAT : Pre heat extruder and heated bed
  • UI_ACTION_COOLDOWN : Disable extruder heater and heated bed
  • UI_ACTION_HEATED_BED_OFF : Turn heated bed off
  • UI_ACTION_EXTRUDER0_OFF : Turn extruder 0 off
  • UI_ACTION_EXTRUDER1_OFF : Turn extruder 1 off
  • UI_ACTION_HEATED_BED_TEMP : Set heated bed temperature
  • UI_ACTION_EXTRUDER0_TEMP : Set extruder 0 temperature
  • UI_ACTION_EXTRUDER1_TEMP : Set extruder 1 temperature
  • UI_ACTION_OPS_OFF : Turn OPS off
  • UI_ACTION_OPS_CLASSIC : Switch OPS to classic mode
  • UI_ACTION_OPS_FAST : Switch OPS to fast mode
  • UI_ACTION_DISABLE_STEPPER : Disable stepper motors
  • UI_ACTION_RESET_EXTRUDER : Set extruder position to 0
  • UI_ACTION_EXTRUDER_RELATIVE : Toggle extruder relative mode
  • UI_ACTION_SELECT_EXTRUDER0 : Make extruder 0 current extruder
  • UI_ACTION_MENU_XPOS : Show x position menu
  • UI_ACTION_MENU_YPOS : Show y position menu
  • UI_ACTION_MENU_ZPOS : Show z position menu
  • UI_ACTION_MENU_XPOSFAST : Show x fast position menu
  • UI_ACTION_MENU_YPOSFAST : Show y fast position menu
  • UI_ACTION_MENU_ZPOSFAST : Show z fast position menu
  • UI_ACTION_MENU_SDCARD : Show sd card menu
  • UI_ACTION_MENU_QUICKSETTINGS : Show quick settings menu
  • UI_ACTION_MENU_EXTRUDER : Show extruder menu
  • UI_ACTION_MENU_POSITIONS : Show positions menu


First you need to define, how your LCD is connected:


Possible values: 0 = No display
1 = LCD Display with 4 bit data bus
2 = LCD Display with 8 bit data bus (is mapped to 1) 3 = LCD Display with I2C connection, 4 bit mode

Then you can define the second line of the greeting message.

#define UI_VERSION_STRING2 "Orig. Mendel"

Now define the number of columns (16, 20 or 24) and number of rows (2 or 4)

#define UI_COLS 16  
#define UI_ROWS 4

Now comes the hard part. You need to identify the pins used to control the display and set them accordingly. The first definition block is for a display connected over I2C. Here you need to set the mask value, not the pin number. That’s why you see _BV(3) for pin 3 (if you start counting at 0). In addition you need to set the PCF8574 address.

If you use a direct connection you could set the RW pin to -1. If you do this, the firmware will wait UI_DELAYPERCHAR microseconds after each byte send. The faster method is to have a RW pin, so the firmware can ask the display if it is ready for the next command.

#if UI_DISPLAY_TYPE==3 // I2C Pin configuration
#define UI_DISPLAY_RS_PIN _BV(4)
#define UI_DISPLAY_RW_PIN _BV(5)
#define UI_DISPLAY_D0_PIN _BV(0)
#define UI_DISPLAY_D1_PIN _BV(1)
#define UI_DISPLAY_D2_PIN _BV(2)
#define UI_DISPLAY_D3_PIN _BV(3)
#define UI_DISPLAY_D4_PIN _BV(0)
#define UI_DISPLAY_D5_PIN _BV(1)
#define UI_DISPLAY_D6_PIN _BV(2)
#define UI_DISPLAY_D7_PIN _BV(3)
// 0x40 till 0x4e for PCF8574
#else // Direct display connections
#define UI_DISPLAY_RS_PIN 16
#define UI_DISPLAY_RW_PIN 17
#define UI_DISPLAY_D0_PIN 23
#define UI_DISPLAY_D1_PIN 29
#define UI_DISPLAY_D2_PIN 25
#define UI_DISPLAY_D3_PIN 27
#define UI_DISPLAY_D4_PIN 23
#define UI_DISPLAY_D5_PIN 29
#define UI_DISPLAY_D6_PIN 25
#define UI_DISPLAY_D7_PIN 27


The firmware gives you complete freedom over the number and functions of your keys. The price you pay is, you have to write the key polling code yourself. Don’t worry, the firmware has predefined macros for the most common types of keys. You have to put the code into the matching 4 functions used by the firmware. All functions are already defined in the keys section of uiconfig.h with some commented samples. But before we start with the function, you should define some key related definitions.

First, tell the firmware if you have any keys at all.

/** Are some keys connected?
0 = No keys attached - disables also menu
1 = Some keys attached */
#define UI_HAS_KEYS 0

If you set it to 0 you can skip the rest of this section.

Most keys bounce the signal when closed/opened. After a short time the signal stabilizes. There is no need to add debounce electronics, all needed is to tell the firmware how long your keys bounce. After that, you can define key repetition behaviour. The default values should give a good starting point.

/** \brief bounce time of keys in milliseconds */
/** \brief First time in ms until repeat of action. */
/** \brief Reduction of repeat time until next execution. */
/** \brief Lowest repeat time. */
#define UI_KEY_MIN_REPEAT 100

Next you define, if you will set the action of one of the keys to UI_ACTION_BACK. If you do, set the value to 0, so the back menü function at the top is removed. This way you can navigate faster through the menus. If you want the back menu entry, set it to 0 even if you have a back key.

#define UI_HAS_BACK_KEY 1

If you have keys attached over I2C, you need to uncomment the define and set the PCF8574 address.

/** Uncomment this, if you have keys connected via i2c to a PCF8574 chip. */
//#define UI_HAS_I2C_KEYS


// Under which address can the key status requested. This is the address of your PCF8574 where the keys are connected-

#define UI_I2C_KEY_ADDRESS 0x40

Ok, now the hard part. We start with the keyboard initialization. This functions is called only once, before the key polling starts. Here we define the pins as input and enable the pull up resistor if required. I2C keys need no code here. Possible macros are listed in the uiconfig file with their description.

void ui_init_keys() {
//  UI_KEYS_INIT_CLICKENCODER_LOW(47,45); // click encoder on pins 47 and 45. Phase is connected with gnd for signals.
//  UI_KEYS_INIT_BUTTON_LOW(43); // push button, connects gnd to pin
// UI_KEYS_INIT_MATRIX(32,47,45,43,41,39,37,35);

The macros for the next three functions are all the same. They are only caused from different points and with different frequencies. The first function is ui_check_keys. This is called from an interrupt and should finish as fast as possible. The only thing you should add here is a directly connected encoder. All I2C key methods are strictly forbidden. They take to much time to be run inside the interrupt. You can add 1-2 directly connected push buttons here if you want.

The second function is ui_check_slow_encoder, which is intended for rotary encodes connected over I2C. This is the only key macro you should add there. As you see, there is already one included, but you may need to change the type or pins or disable it, if you use I2C keys without encoder.

The last function is ui_check_slow_keys. Here you add the same key macro as in ui_check_slow_encoder, if you have anything there plus all keys not defined until now. This function is called from the main thread and can be interrupted any time, so no big things happen if it takes some ticks longer.

void ui_check_keys(int &action) {
//  UI_KEYS_CLICKENCODER_LOW_REV(47,45); // click encoder on pins 47 and 45. Phase is connected with gnd for signals.
//  UI_KEYS_BUTTON_LOW(43,UI_ACTION_OK); // push button, connects gnd to pin
inline void ui_check_slow_encoder() {
#ifdef UI_HAS_I2C_KEYS
  byte keymask = i2c_readNak(); // Read current key mask
  // Add I2C click encoder tests here, all other i2c tests and a copy of the encoder test belog in ui_check_slow_keys
  UI_KEYS_I2C_CLICKENCODER_LOW_REV(_BV(2),_BV(0)); // click encoder on pins 0 and 2. Phase is connected with gnd for signals.
void ui_check_slow_keys(int &action) {
#ifdef UI_HAS_I2C_KEYS
    i2c_start_wait(UI_I2C_KEY_ADDRESS+I2C_READ);  // Read keymask from i2c for the following tests
    byte keymask = i2c_readNak(); // Read current key mask
    // Add I2C key tests here
    UI_KEYS_I2C_CLICKENCODER_LOW_REV(_BV(2),_BV(0)); // click encoder on pins 0 and 2. Phase is connected with gnd for signals.
    UI_KEYS_I2C_BUTTON_LOW(_BV(1),UI_ACTION_OK); // push button, connects gnd to pin  
    UI_KEYS_I2C_BUTTON_LOW(_BV(3),UI_ACTION_BACK); // push button, connects gnd to pin  
    UI_KEYS_I2C_BUTTON_LOW(_BV(4),UI_ACTION_MENU_QUICKSETTINGS); // push button, connects gnd to pin  
    UI_KEYS_I2C_BUTTON_LOW(_BV(5),UI_ACTION_MENU_EXTRUDER); // push button, connects gnd to pin  
    UI_KEYS_I2C_BUTTON_LOW(_BV(6),UI_ACTION_MENU_POSITIONS); // push button, connects gnd to pin  

 // UI_KEYS_MATRIX(32,47,45,43,41,39,37,35);


You find the buzzer configuration near the start of the file. The comments should be enough, to understand the configuration.

/** Select type of beeper
0 = none
1 = Piezo connected to pin
2 = Piezo connected to a pin over I2C */
#define BEEPER_TYPE 0 
#define BEEPER_PIN 42
#define BEEPER_ADDRESS 0x40 // I2C address of the chip with the beeper pin
#define BEEPER_PIN _BV(7)  // Bit value for pin 8
#define COMPILE_I2C_DRIVER  // We need the I2C driver as we are using i2c

Beeper sound definitions for short beeps during key actions
and longer beeps for important actions.
Parameter is is delay in microseconds and the secons is the number of repetitions.
Values must be in range 1..255 */

Menu definition

At the start of the file you can select the language for your menu. #define UI_LANGUAGE 0

0 is english, 1 is german and 2 is dutch. With some luck nice users of the firmware will contribute additional languages. To define your own language go into uilang.h At the end you will find this, where you can write your own translations:

// *************************************************************************************
//                             User defined language
// If you need a language not mentioned above, you can translate this dummy entry.
// If you want it added permanently to the distribution, spend it to the community under
// GPL V3. Only new and complete translations are put into the official distribution!
// *************************************************************************************

#if UI_LANGUAGE==1000

To use it, select 1000 as language.

Thats all needed to get the complete menu and info pages. If you want more information pages or additional menu entries, other ordering etc. search for

/* ============ MENU definition ================

and make your changes. Read the comments and look at the definitions and you should gasp, how to modify it. Be careful to update the menu entry counters to match the number of entries!

Boots Industries