Skip to content
Ryan Jarvis edited this page Dec 15, 2018 · 7 revisions

User Interface

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 4x4 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

Display

The current firmware supports LCD display using a HD44780 or compatible driver. This is an 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 potentiometer 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.

Keys

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 than 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!

Configuration

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

Concept

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 a 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_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 : Unmount 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 direction
UI_ACTION_STEPS_Y : Change steps per mm in y direction
UI_ACTION_STEPS_Z : Change steps per mm in z direction
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 extruder
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 extruder heat manager
UI_ACTION_EXTR_WATCH_PERIOD : Change temperature stabilize 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

Display

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

#define UI_DISPLAY_TYPE 1

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_ENABLE_PIN _BV(6)
#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
#define UI_DISPLAY_I2C_ADDRESS 0x4e
#else // Direct display connections
#define UI_DISPLAY_RS_PIN 16
#define UI_DISPLAY_RW_PIN 17
#define UI_DISPLAY_ENABLE_PIN 31
#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
#define UI_DELAYPERCHAR 320
#endif

Keys

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 behavior. The default values should give a good starting point.

/** \brief bounce time of keys in milliseconds */
#define UI_KEY_BOUNCETIME 10
/** \brief First time in ms until repeat of action. */
#define UI_KEY_FIRST_REPEAT 500
/** \brief Reduction of repeat time until next execution. */
#define UI_KEY_REDUCE_REPEAT 50
/** \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 menu 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 too 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
  i2c_start_wait(UI_I2C_KEY_ADDRESS+I2C_READ);
  byte keymask = i2c_readNak(); // Read current key mask
  i2c_stop();
  // Add I2C click encoder tests here, all other i2c tests and a copy of the encoder test belong 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.
#endif
}
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
    i2c_stop();
    // 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
#endif

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

Buzzer

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

#if BEEPER_TYPE==1
#define BEEPER_PIN 42
#endif
#if BEEPER_TYPE==2
#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
#endif

/**
Beeper sound definitions for short beeps during key actions
and longer beeps for important actions.
Parameter is is delay in microseconds and the seconds is the number of repetitions.
Values must be in range 1..255
*/
#define BEEPER_SHORT_SEQUENCE 1,1
#define BEEPER_LONG_SEQUENCE 5,5

Menu definition

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

0 is english and 1 is german. 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!