Browse Source

more work on firmware, support for full graphic smart lcd.

Thomas Buck 2 years ago
parent
commit
fb00cf83a5
14 changed files with 981 additions and 96 deletions
  1. 27
    9
      include/config.h
  2. 23
    1
      include/config_pins.h
  3. 5
    2
      include/data.h
  4. 4
    0
      include/lcd.h
  5. 37
    4
      include/statemachine.h
  6. 12
    0
      include/steppers.h
  7. 17
    2
      platformio.ini
  8. 91
    15
      src/data.cpp
  9. 36
    3
      src/encoder.cpp
  10. 240
    8
      src/lcd.cpp
  11. 6
    8
      src/main.cpp
  12. 223
    13
      src/statemachine.cpp
  13. 141
    14
      src/states.cpp
  14. 119
    17
      src/steppers.cpp

+ 27
- 9
include/config.h View File

7
 
7
 
8
 #define FIRMWARE_VERSION "0.1"
8
 #define FIRMWARE_VERSION "0.1"
9
 
9
 
10
-#define LED_BLINK_INTERVAL 500
10
+#define LED_BLINK_INTERVAL 1000
11
 #define DEBOUNCE_DELAY 50
11
 #define DEBOUNCE_DELAY 50
12
 
12
 
13
 #define ENCODER_CLICK_BEEP_FREQ 2000
13
 #define ENCODER_CLICK_BEEP_FREQ 2000
14
 #define ENCODER_CLICK_BEEP_TIME 50
14
 #define ENCODER_CLICK_BEEP_TIME 50
15
 
15
 
16
+#define HOMING_BEEP_FREQ 3000
17
+#define HOMING_BEEP_TIME 100
18
+
19
+#define KILL_BEEP_FREQ 3000
20
+#define KILL_BEEP_TIME 100
21
+#define KILL_BEEP_REPEAT 5
22
+
16
 /***************************************
23
 /***************************************
17
  ********** Hardware Settings **********
24
  ********** Hardware Settings **********
18
  ***************************************/
25
  ***************************************/
19
 
26
 
20
-#define USE_20X4_TEXT_LCD
21
-//#define USE_FULL_GRAPHIC_LCD
22
-
23
 // xy steps per mm
27
 // xy steps per mm
24
 #define XY_BELT_PITCH 2.0
28
 #define XY_BELT_PITCH 2.0
25
 #define XY_PULLEY_TEETH 40.0
29
 #define XY_PULLEY_TEETH 40.0
34
 #define Z_STEPS_PER_MM (Z_MOTOR_STEPS_PER_REV / Z_ROD_PITCH)
38
 #define Z_STEPS_PER_MM (Z_MOTOR_STEPS_PER_REV / Z_ROD_PITCH)
35
 
39
 
36
 // e steps per mm
40
 // e steps per mm
41
+// 1/2 turn of output is movement range
42
+// gear box factor 3:1 output:input
43
+// 3/2 turns of motor equals 100% movement
44
+// (16 * 200) = 3200 steps for motor turn
45
+// 3200 * 3 / 2 = 4800 steps for 3/2 turn
46
+// 4800 / 100 = 48 steps for one percent of movement
47
+#define GEARBOX_MULT 3
48
+#define OUTPUT_TURN_DIV 2
37
 #define E_MICRO_STEPS 16.0
49
 #define E_MICRO_STEPS 16.0
38
 #define E_MOTOR_STEPS_PER_REV (200.0 * E_MICRO_STEPS)
50
 #define E_MOTOR_STEPS_PER_REV (200.0 * E_MICRO_STEPS)
39
-#define E_STEPS_PER_MM (E_MOTOR_STEPS_PER_REV / 42) // TODO
51
+#define E_STEPS_PER_PERCENT (E_MOTOR_STEPS_PER_REV * GEARBOX_MULT / OUTPUT_TURN_DIV / 100.0)
40
 
52
 
41
 // travel lengths
53
 // travel lengths
42
 #define X_AXIS_MIN -5.0 // in mm
54
 #define X_AXIS_MIN -5.0 // in mm
48
 #define E_AXIS_MIN 0.0 // in mm
60
 #define E_AXIS_MIN 0.0 // in mm
49
 #define E_AXIS_MAX 6.0 // in mm
61
 #define E_AXIS_MAX 6.0 // in mm
50
 
62
 
63
+//   0 degree =   0 percent =  pi = 0mm
64
+// 180 degree = 100 percent = 2pi = 6mm
65
+// (cos(pi + x / 100 * pi) + 1) / 2 * 6mm
66
+#define E_PERCENT_TO_MM(x) ((cos(PI + (x * PI / 100.0)) + 1.0) / 2.0 * E_AXIS_MAX)
67
+#define E_MM_TO_PERCENT(x) ((acos((x * 2.0 / E_AXIS_MAX) - 1.0) - PI) * 100.0 / PI)
68
+
51
 // maximum speeds
69
 // maximum speeds
52
 #define XY_MAX_SPEED 50.0 // in mm/s
70
 #define XY_MAX_SPEED 50.0 // in mm/s
53
 #define Z_MAX_SPEED 20.0 // in mm/s
71
 #define Z_MAX_SPEED 20.0 // in mm/s
54
-#define E_MAX_SPEED 10.0 // in mm/s
72
+#define E_MAX_SPEED 50.0 // in percent/s
55
 
73
 
56
 // homing speeds
74
 // homing speeds
57
 #define XY_FAST_HOME_SPEED 2.5 // in mm/s
75
 #define XY_FAST_HOME_SPEED 2.5 // in mm/s
58
 #define XY_SLOW_HOME_SPEED 1.0 // in mm/s
76
 #define XY_SLOW_HOME_SPEED 1.0 // in mm/s
59
 #define Z_FAST_HOME_SPEED 2.0 // in mm/s
77
 #define Z_FAST_HOME_SPEED 2.0 // in mm/s
60
 #define Z_SLOW_HOME_SPEED 1.0 // in mm/s
78
 #define Z_SLOW_HOME_SPEED 1.0 // in mm/s
61
-#define E_FAST_HOME_SPEED 0.1 // in mm/s
62
-#define E_SLOW_HOME_SPEED 0.05 // in mm/s
79
+#define E_FAST_HOME_SPEED 10.0 // in percent/s
80
+#define E_SLOW_HOME_SPEED 5.0 // in percent/s
63
 
81
 
64
 // accelerations
82
 // accelerations
65
 #define XY_MAX_ACCEL 100.0 // in mm/s^2
83
 #define XY_MAX_ACCEL 100.0 // in mm/s^2
66
 #define Z_MAX_ACCEL 50.0 // in mm/s^2
84
 #define Z_MAX_ACCEL 50.0 // in mm/s^2
67
-#define E_MAX_ACCEL 20.0 // in mm/s^2
85
+#define E_MAX_ACCEL 1000.0 // in percent/s^2
68
 
86
 
69
 // axis movement directions (1.0 normal, -1.0 inverted)
87
 // axis movement directions (1.0 normal, -1.0 inverted)
70
 #define X_AXIS_MOVEMENT_DIR 1.0
88
 #define X_AXIS_MOVEMENT_DIR 1.0

+ 23
- 1
include/config_pins.h View File

81
 
81
 
82
 #ifdef USE_FULL_GRAPHIC_LCD
82
 #ifdef USE_FULL_GRAPHIC_LCD
83
 
83
 
84
-// TODO
84
+// based on https://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
85
+
86
+// STOP / KILL button
87
+#define KILL_PIN 41
88
+
89
+// lcd pins
90
+#define LCD_PINS_CS 16
91
+#define LCD_PINS_MOSI 17
92
+#define LCD_PINS_SCK 23
93
+
94
+// encoder pins
95
+#define BTN_EN1 31
96
+#define BTN_EN2 33
97
+#define BTN_ENC 35
98
+
99
+// beeper
100
+#define BEEPER 37
85
 
101
 
86
 #endif // USE_FULL_GRAPHIC_LCD
102
 #endif // USE_FULL_GRAPHIC_LCD
87
 
103
 
134
 #define E_HOMING_DIR -1.0
150
 #define E_HOMING_DIR -1.0
135
 #define E_ENDSTOP_PIN E_MIN_PIN
151
 #define E_ENDSTOP_PIN E_MIN_PIN
136
 #endif
152
 #endif
153
+
154
+#ifdef KILL_PIN
155
+#if (KILL_PIN == -1)
156
+#undef KILL_PIN
157
+#endif
158
+#endif // KILL_PIN

+ 5
- 2
include/data.h View File

19
 void data_init(void);
19
 void data_init(void);
20
 void data_eeprom_write(void);
20
 void data_eeprom_write(void);
21
 
21
 
22
+bool data_eeprom_read(void);
23
+const char *data_eeprom_error(void);
24
+
22
 struct data_config_options *data_options(void);
25
 struct data_config_options *data_options(void);
23
 
26
 
24
 unsigned int data_preset_count(void);
27
 unsigned int data_preset_count(void);
25
 struct data_config_preset *data_preset(unsigned int i);
28
 struct data_config_preset *data_preset(unsigned int i);
26
-void data_preset_add(struct data_config_preset preset);
27
-void data_preset_remove(unsigned int i);
29
+bool data_preset_add(struct data_config_preset preset);
30
+bool data_preset_remove(unsigned int i);
28
 
31
 
29
 #endif // _DATA_H_
32
 #endif // _DATA_H_

+ 4
- 0
include/lcd.h View File

2
 #define _LCD_H_
2
 #define _LCD_H_
3
 
3
 
4
 void lcd_init(void);
4
 void lcd_init(void);
5
+void lcd_loop(void);
5
 
6
 
6
 void lcd_clear(void);
7
 void lcd_clear(void);
7
 void lcd_set_heading(const char *heading);
8
 void lcd_set_heading(const char *heading);
8
 void lcd_set_text(const char *text);
9
 void lcd_set_text(const char *text);
10
+void lcd_set_menu_text(int line, const char *text);
11
+
12
+int lcd_text_lines(void);
9
 
13
 
10
 #endif // _LCD_H_
14
 #endif // _LCD_H_

+ 37
- 4
include/statemachine.h View File

3
 
3
 
4
 #include <Array.h>
4
 #include <Array.h>
5
 
5
 
6
+#define STATE_ARRAY_SIZE 42
7
+
8
+template <typename T, size_t N>
9
+void array_print(Array<T, N> *arr);
10
+
11
+template <typename T, size_t N>
12
+void array_insert_at_pos(Array<T, N> *arr, T value, size_t pos);
13
+
6
 struct StateMachineInput {
14
 struct StateMachineInput {
7
     StateMachineInput(int c, int e, int k, int m)
15
     StateMachineInput(int c, int e, int k, int m)
8
             : click(c), encoder(e), kill(k), motors_done(m) { };
16
             : click(c), encoder(e), kill(k), motors_done(m) { };
58
 
66
 
59
 class StateMenu : public State {
67
 class StateMenu : public State {
60
 public:
68
 public:
61
-    StateMenu(State *_parent = NULL);
69
+    StateMenu(State *_parent = NULL, bool _show_parent = true);
62
     virtual void setChild(State *_child);
70
     virtual void setChild(State *_child);
63
 
71
 
64
     void addChild(State *_child, int pos = -1);
72
     void addChild(State *_child, int pos = -1);
67
     virtual void inState(StateMachineInput smi);
75
     virtual void inState(StateMachineInput smi);
68
 
76
 
69
 private:
77
 private:
70
-    int menuPos;
71
-    Array<State *, 42> children;
78
+    void display(void);
79
+
80
+    bool show_parent;
81
+    int menuPos, menuOff;
82
+    Array<State *, STATE_ARRAY_SIZE> children;
72
 };
83
 };
73
 
84
 
74
 class StateDynamicMenu : public State {
85
 class StateDynamicMenu : public State {
93
     GetFuncPtr getFunc;
104
     GetFuncPtr getFunc;
94
     CallFuncPtr callFunc;
105
     CallFuncPtr callFunc;
95
 
106
 
107
+    int menuPos, menuOff;
96
     int count;
108
     int count;
97
-    Array<const char *, 42> contents;
109
+    Array<const char *, STATE_ARRAY_SIZE> contents;
110
+};
111
+
112
+template <typename T>
113
+class StateValue : public State {
114
+public:
115
+    StateValue(State *_parent, T &_value, T _min, T _max);
116
+
117
+    typedef void(*UpdateFuncPtr)(T value);
118
+
119
+    void onUpdate(UpdateFuncPtr func);
120
+
121
+    virtual void enterState(void);
122
+    virtual void inState(StateMachineInput smi);
123
+
124
+private:
125
+    void display(void);
126
+
127
+    T &value;
128
+    T min, max;
129
+    UpdateFuncPtr updateFunc;
98
 };
130
 };
99
 
131
 
132
+
100
 #endif // _STATE_MACHINE_H_
133
 #endif // _STATE_MACHINE_H_

+ 12
- 0
include/steppers.h View File

12
 int steppers_move_z(long pos);
12
 int steppers_move_z(long pos);
13
 int steppers_move_e(long pos);
13
 int steppers_move_e(long pos);
14
 
14
 
15
+void steppers_kill(void);
16
+
17
+void steppers_set_speed_x(float speed);
18
+void steppers_set_speed_y(float speed);
19
+void steppers_set_speed_z(float speed);
20
+void steppers_set_speed_e(float speed);
21
+
22
+void steppers_set_accel_x(float accel);
23
+void steppers_set_accel_y(float accel);
24
+void steppers_set_accel_z(float accel);
25
+void steppers_set_accel_e(float accel);
26
+
15
 #endif // _STEPPERS_H_
27
 #endif // _STEPPERS_H_

+ 17
- 2
platformio.ini View File

9
 ; https://docs.platformio.org/page/projectconf.html
9
 ; https://docs.platformio.org/page/projectconf.html
10
 
10
 
11
 [platformio]
11
 [platformio]
12
-default_envs = arduino
12
+default_envs = ramps_lcd2004, ramps_lcd12864
13
 
13
 
14
-[env:arduino]
14
+[env:ramps_lcd2004]
15
 platform = atmelavr
15
 platform = atmelavr
16
 board = megaatmega2560
16
 board = megaatmega2560
17
 framework = arduino
17
 framework = arduino
18
+build_flags = -D USE_20X4_TEXT_LCD -Wno-sign-compare
18
 upload_port = /dev/ttyUSB1
19
 upload_port = /dev/ttyUSB1
19
 monitor_port = /dev/ttyUSB1
20
 monitor_port = /dev/ttyUSB1
20
 monitor_speed = 115200
21
 monitor_speed = 115200
23
     https://github.com/waspinator/AccelStepper
24
     https://github.com/waspinator/AccelStepper
24
     https://github.com/mathertel/RotaryEncoder
25
     https://github.com/mathertel/RotaryEncoder
25
     https://github.com/janelia-arduino/Array
26
     https://github.com/janelia-arduino/Array
27
+
28
+[env:ramps_lcd12864]
29
+platform = atmelavr
30
+board = megaatmega2560
31
+framework = arduino
32
+build_flags = -D USE_FULL_GRAPHIC_LCD -Wno-sign-compare
33
+upload_port = /dev/ttyUSB1
34
+monitor_port = /dev/ttyUSB1
35
+monitor_speed = 115200
36
+lib_deps =
37
+    u8g2
38
+    https://github.com/waspinator/AccelStepper
39
+    https://github.com/mathertel/RotaryEncoder
40
+    https://github.com/janelia-arduino/Array

+ 91
- 15
src/data.cpp View File

5
 #include "config_pins.h"
5
 #include "config_pins.h"
6
 #include "data.h"
6
 #include "data.h"
7
 
7
 
8
+// TODO make defines platform specific
8
 #define EEPROM_SIZE 4096
9
 #define EEPROM_SIZE 4096
10
+#define RAM_SIZE (8192 / 2)
9
 
11
 
10
 struct data_config {
12
 struct data_config {
11
     uint8_t data_schema_version;
13
     uint8_t data_schema_version;
16
 };
18
 };
17
 
19
 
18
 static struct data_config d;
20
 static struct data_config d;
21
+static const char *last_error = "";
19
 
22
 
20
-static unsigned int max_presets(void) {
23
+static unsigned int max_presets_eeprom(void) {
21
     unsigned int s = EEPROM_SIZE - sizeof(struct data_config) + sizeof(struct data_config_preset *);
24
     unsigned int s = EEPROM_SIZE - sizeof(struct data_config) + sizeof(struct data_config_preset *);
22
     return s / sizeof(struct data_config_preset);
25
     return s / sizeof(struct data_config_preset);
23
 }
26
 }
24
 
27
 
28
+static unsigned int max_presets_ram(void) {
29
+    unsigned int s = RAM_SIZE - sizeof(struct data_config) + sizeof(struct data_config_preset *);
30
+    return s / sizeof(struct data_config_preset);
31
+}
32
+
33
+static unsigned int max_presets(void) {
34
+    unsigned int eeprom = max_presets_eeprom();
35
+    unsigned int ram = max_presets_ram();
36
+    return (eeprom < ram) ? eeprom : ram;
37
+}
38
+
25
 static uint32_t data_checksum(struct data_config *data) {
39
 static uint32_t data_checksum(struct data_config *data) {
26
     uint32_t c = 0;
40
     uint32_t c = 0;
27
 
41
 
40
     return c;
54
     return c;
41
 }
55
 }
42
 
56
 
43
-static bool data_eeprom_read(void) {
57
+const char *data_eeprom_error(void) {
58
+    return last_error;
59
+}
60
+
61
+bool data_eeprom_read(void) {
44
     struct data_config config;
62
     struct data_config config;
45
     uint8_t *data = (uint8_t *)&config;
63
     uint8_t *data = (uint8_t *)&config;
46
 
64
 
51
     }
69
     }
52
 
70
 
53
     if (config.preset_count > 0) {
71
     if (config.preset_count > 0) {
54
-        config.presets = (struct data_config_preset *)malloc(config.preset_count * sizeof(struct data_config_preset));
55
-        if (config.presets == NULL) {
56
-            Serial.print(F("Alloc "));
72
+        if (config.preset_count > max_presets()) {
73
+            last_error = "Preset";
57
             return false;
74
             return false;
58
         }
75
         }
59
 
76
 
60
-        if (config.preset_count > max_presets()) {
61
-            Serial.print(F("Preset "));
77
+        config.presets = (struct data_config_preset *)malloc(config.preset_count * sizeof(struct data_config_preset));
78
+        if (config.presets == NULL) {
79
+            last_error = "Alloc";
62
             return false;
80
             return false;
63
         }
81
         }
64
 
82
 
75
     }
93
     }
76
 
94
 
77
     // verify checksum
95
     // verify checksum
96
+    uint32_t read_checksum = config.checksum;
97
+    config.checksum = 0;
78
     uint32_t checksum = data_checksum(&config);
98
     uint32_t checksum = data_checksum(&config);
79
-    if (config.checksum == checksum) {
99
+    if (read_checksum == checksum) {
80
         // verify version
100
         // verify version
81
         if (config.data_schema_version == DATA_SCHEMA_VERSION) {
101
         if (config.data_schema_version == DATA_SCHEMA_VERSION) {
82
             if (d.presets != NULL) {
102
             if (d.presets != NULL) {
84
             }
104
             }
85
             d = config;
105
             d = config;
86
 
106
 
107
+            last_error = "";
87
             return true;
108
             return true;
88
         } else {
109
         } else {
89
-            Serial.print(F("Version "));
110
+            last_error = "Version";
90
             return false;
111
             return false;
91
         }
112
         }
92
     } else {
113
     } else {
93
-        Serial.print(F("Checksum "));
114
+        Serial.print("read=");
115
+        Serial.print(config.checksum);
116
+        Serial.print(" calc=");
117
+        Serial.println(checksum);
118
+        last_error = "Checksum";
94
         return false;
119
         return false;
95
     }
120
     }
96
 }
121
 }
97
 
122
 
98
 void data_eeprom_write(void) {
123
 void data_eeprom_write(void) {
124
+    d.checksum = 0;
99
     d.checksum = data_checksum(&d);
125
     d.checksum = data_checksum(&d);
100
 
126
 
101
     // write meta-data and settings
127
     // write meta-data and settings
132
 
158
 
133
     d.presets = NULL;
159
     d.presets = NULL;
134
 
160
 
161
+    Serial.print(F("EEPROM max presets: "));
162
+    Serial.println(max_presets());
163
+
135
     Serial.print(F("EEPROM read... "));
164
     Serial.print(F("EEPROM read... "));
136
     if (!data_eeprom_read()) {
165
     if (!data_eeprom_read()) {
137
-        Serial.println(F("Error"));
166
+        Serial.print(last_error);
167
+        Serial.println(F(" Error"));
138
     } else {
168
     } else {
139
         Serial.println(F("Ok"));
169
         Serial.println(F("Ok"));
140
     }
170
     }
155
     return NULL;
185
     return NULL;
156
 }
186
 }
157
 
187
 
158
-void data_preset_add(struct data_config_preset preset) {
159
-
188
+bool data_preset_add(struct data_config_preset preset) {
189
+    if ((d.preset_count == 0) || (d.presets == NULL)) {
190
+        d.preset_count = 1;
191
+        d.presets = (struct data_config_preset *)malloc(d.preset_count * sizeof(struct data_config_preset));
192
+        if (d.presets == NULL) {
193
+            d.preset_count = 0;
194
+            last_error = "Alloc";
195
+            return false;
196
+        } else {
197
+            d.presets[d.preset_count - 1] = preset;
198
+            return true;
199
+        }
200
+    } else if (d.preset_count < max_presets()) {
201
+        d.preset_count += 1;
202
+        struct data_config_preset *new_mem = (struct data_config_preset *)realloc(d.presets, d.preset_count * sizeof(struct data_config_preset));
203
+        if (new_mem == NULL) {
204
+            d.preset_count -= 1;
205
+            last_error = "Realloc";
206
+            return false;
207
+        } else {
208
+            d.presets = new_mem;
209
+            d.presets[d.preset_count - 1] = preset;
210
+            return true;
211
+        }
212
+    } else {
213
+        return false;
214
+    }
160
 }
215
 }
161
 
216
 
162
-void data_preset_remove(unsigned int i) {
163
-
217
+bool data_preset_remove(unsigned int i) {
218
+    if (d.preset_count == 1) {
219
+        d.preset_count = 0;
220
+        free(d.presets);
221
+        d.presets = NULL;
222
+        return true;
223
+    } else if (d.preset_count > 1) {
224
+        for (int j = i; j < (d.preset_count - 1); j++) {
225
+            d.presets[j] = d.presets[j + 1];
226
+        }
227
+        d.preset_count -= 1;
228
+        struct data_config_preset *new_mem = (struct data_config_preset *)realloc(d.presets, d.preset_count * sizeof(struct data_config_preset));
229
+        if (new_mem == NULL) {
230
+            d.preset_count += 1;
231
+            last_error = "Realloc";
232
+            return false;
233
+        } else {
234
+            d.presets = new_mem;
235
+            return true;
236
+        }
237
+    } else {
238
+        return true; // nothing to delete
239
+    }
164
 }
240
 }

+ 36
- 3
src/encoder.cpp View File

6
 #include "debounce.h"
6
 #include "debounce.h"
7
 #include "encoder.h"
7
 #include "encoder.h"
8
 
8
 
9
+//#define DEBUG_ENCODER
10
+
9
 static Debouncer click(BTN_ENC);
11
 static Debouncer click(BTN_ENC);
10
 static int click_state = 0;
12
 static int click_state = 0;
11
 static bool ignore_until_next_unclick = false;
13
 static bool ignore_until_next_unclick = false;
12
 
14
 
15
+#ifdef KILL_PIN
13
 static Debouncer kill(KILL_PIN);
16
 static Debouncer kill(KILL_PIN);
14
 static int kill_state = 0;
17
 static int kill_state = 0;
18
+#endif // KILL_PIN
15
 
19
 
16
-static RotaryEncoder encoder(BTN_EN1, BTN_EN2, RotaryEncoder::LatchMode::TWO03);
20
+static RotaryEncoder encoder(BTN_EN1, BTN_EN2, RotaryEncoder::LatchMode::FOUR3);
17
 static int pos = 0;
21
 static int pos = 0;
18
 
22
 
19
 void encoder_init(void) {
23
 void encoder_init(void) {
20
-    pinMode(BTN_ENC, INPUT);
21
-    pinMode(KILL_PIN, INPUT);
24
+    pinMode(BTN_ENC, INPUT_PULLUP);
25
+
26
+#ifdef KILL_PIN
27
+    pinMode(KILL_PIN, INPUT_PULLUP);
28
+#endif // KILL_PIN
22
 }
29
 }
23
 
30
 
24
 void encoder_run(void) {
31
 void encoder_run(void) {
32
         click_state = cs;
39
         click_state = cs;
33
     }
40
     }
34
 
41
 
42
+#ifdef KILL_PIN
35
     kill_state = kill.poll();
43
     kill_state = kill.poll();
44
+#endif // KILL_PIN
36
 
45
 
37
     encoder.tick();
46
     encoder.tick();
38
 }
47
 }
41
     int new_pos = encoder.getPosition();
50
     int new_pos = encoder.getPosition();
42
     int diff = new_pos - pos;
51
     int diff = new_pos - pos;
43
     pos = new_pos;
52
     pos = new_pos;
53
+
54
+#ifdef DEBUG_ENCODER
55
+    if (diff != 0) {
56
+        Serial.print("encoder_change: ");
57
+        Serial.print(diff);
58
+        Serial.print(" ticks: ");
59
+        Serial.println(new_pos);
60
+    }
61
+#endif // DEBUG_ENCODER
62
+
44
     return diff;
63
     return diff;
45
 }
64
 }
46
 
65
 
51
     if (r == 1) {
70
     if (r == 1) {
52
         click_state = 0;
71
         click_state = 0;
53
         ignore_until_next_unclick = true;
72
         ignore_until_next_unclick = true;
73
+
74
+#ifdef DEBUG_ENCODER
75
+        Serial.println("encoder_click: 1");
76
+#endif // DEBUG_ENCODER
54
     }
77
     }
55
 
78
 
56
     return r;
79
     return r;
57
 }
80
 }
58
 
81
 
59
 int kill_switch(void) {
82
 int kill_switch(void) {
83
+#ifdef KILL_PIN
84
+#ifdef DEBUG_ENCODER
85
+    if (kill_state == 1) {
86
+        Serial.println("kill_switch: 1");
87
+    }
88
+#endif // DEBUG_ENCODER
89
+
60
     return kill_state;
90
     return kill_state;
91
+#else
92
+    return 0;
93
+#endif // KILL_PIN
61
 }
94
 }

+ 240
- 8
src/lcd.cpp View File

9
 #endif
9
 #endif
10
 
10
 
11
 #ifdef USE_20X4_TEXT_LCD
11
 #ifdef USE_20X4_TEXT_LCD
12
+
12
 #include <LiquidCrystal.h>
13
 #include <LiquidCrystal.h>
14
+
15
+#define LCD_HEADING_LINES 1
16
+#define LCD_HEADING_WIDTH 20
17
+#define LCD_TEXT_LINES 3
18
+#define LCD_TEXT_WIDTH 20
19
+
13
 LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5, LCD_PINS_D6, LCD_PINS_D7);
20
 LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5, LCD_PINS_D6, LCD_PINS_D7);
21
+
14
 #endif // USE_20X4_TEXT_LCD
22
 #endif // USE_20X4_TEXT_LCD
15
 
23
 
16
 #ifdef USE_FULL_GRAPHIC_LCD
24
 #ifdef USE_FULL_GRAPHIC_LCD
17
-// TODO
25
+
26
+#include <U8g2lib.h>
27
+
28
+#define LCD_HEADING_LINES 1
29
+#define LCD_HEADING_WIDTH 15
30
+#define LCD_TEXT_LINES 5
31
+#define LCD_TEXT_WIDTH 25
32
+
33
+#define LCD_HEADING_FONT u8g2_font_torussansbold8_8r
34
+#define LCD_TEXT_FONT u8g2_font_5x7_tr
35
+
36
+#define LCD_HEADING_TEXT_OFFSET 3
37
+#define LCD_HEADING_HEIGHT 8
38
+#define LCD_TEXT_HEIGHT 9
39
+
40
+U8G2_ST7920_128X64_1_SW_SPI lcd(U8G2_R0, LCD_PINS_SCK, LCD_PINS_MOSI, LCD_PINS_CS);
41
+
18
 #endif // USE_FULL_GRAPHIC_LCD
42
 #endif // USE_FULL_GRAPHIC_LCD
19
 
43
 
44
+String heading[LCD_HEADING_LINES];
45
+String text[LCD_TEXT_LINES];
46
+
47
+String heading_pre, heading_post;
48
+String text_pre, text_post;
49
+int heading_direction, text_direction;
50
+
51
+String menu_pre[LCD_TEXT_LINES], menu_post[LCD_TEXT_LINES];
52
+int menu_dir[LCD_TEXT_LINES];
53
+
54
+boolean redraw = false;
55
+
56
+enum lcd_text_mode {
57
+    lcd_mode_none,
58
+    lcd_mode_multiline,
59
+    lcd_mode_menu
60
+};
61
+enum lcd_text_mode text_mode = lcd_mode_none;
62
+
63
+#define SCROLL_DELAY 500
64
+unsigned long last_scroll_time = 0;
65
+
66
+void lcd_shorten_multiline(String s[], int n, int w, String *remainder) {
67
+    // if a line is longer then w, take end off and put in front of next line
68
+    String for_next_line = "";
69
+    for (int i = 0; i < n; i++) {
70
+        s[i] = for_next_line + s[i];
71
+        for_next_line = "";
72
+        if (s[i].length() > w) {
73
+            for_next_line = s[i].substring(w);
74
+            s[i] = s[i].substring(0, w);
75
+        }
76
+    }
77
+
78
+    // if something remains at end, store remainder, if given, otherwise leave at last line
79
+    if (remainder != NULL) {
80
+        *remainder = for_next_line;
81
+    } else {
82
+        s[n - 1] = s[n - 1] + for_next_line;
83
+    }
84
+
85
+    last_scroll_time = millis();
86
+}
87
+
88
+void lcd_scroll_multiline(String s[], int n, int w, String &pre, String &post, int &dir) {
89
+    if (dir == 0) {
90
+        // switch directions if done scrolling in current direction
91
+        if (post.length() == 0) {
92
+            dir = 1;
93
+            return;
94
+        }
95
+
96
+        // take first char of first line, append to pre
97
+        pre = pre + s[0][0];
98
+        s[0] = s[0].substring(1);
99
+
100
+        // shift now empty spot to the left through lines
101
+        for (int i = 1; i < n; i++) {
102
+            s[i - 1] = s[i - 1] + s[i][0];
103
+            s[i] = s[i].substring(1);
104
+        }
105
+
106
+        // fill empty spot at end of last line with first char of post
107
+        s[n - 1] = s[n - 1] + post[0];
108
+        post = post.substring(1);
109
+    } else {
110
+        // switch directions if done scrolling in current direction
111
+        if (pre.length() == 0) {
112
+            dir = 0;
113
+            return;
114
+        }
115
+
116
+        // take last char of last line, prepend to post
117
+        post = s[n - 1][s[n - 1].length() - 1] + post;
118
+        s[n - 1] = s[n - 1].substring(0, s[n - 1].length() - 1);
119
+
120
+        // shift now empty sport to the right through lines
121
+        for (int i = n - 1; i >= 1; i--) {
122
+            s[i] = s[i - 1][s[i - 1].length() - 1] + s[i];
123
+            s[i - 1] = s[i - 1].substring(0, s[i - 1].length() - 1);
124
+        }
125
+
126
+        // fill empty spot at beginning with last char of pre
127
+        s[0] = pre[pre.length() - 1] + s[0];
128
+        pre = pre.substring(0, pre.length() - 1);
129
+    }
130
+
131
+    redraw = true;
132
+}
133
+
134
+void lcd_scrolling(void) {
135
+    if (text_mode != lcd_mode_none) {
136
+        if ((heading_pre.length() > 0) || (heading_post.length() > 0)) {
137
+            lcd_scroll_multiline(heading, LCD_HEADING_LINES, LCD_HEADING_WIDTH,
138
+                                 heading_pre, heading_post, heading_direction);
139
+        }
140
+    }
141
+
142
+    if (text_mode == lcd_mode_multiline) {
143
+        if ((text_pre.length() > 0) || (text_post.length() > 0)) {
144
+            lcd_scroll_multiline(text, LCD_TEXT_LINES, LCD_TEXT_WIDTH,
145
+                                 text_pre, text_post, text_direction);
146
+        }
147
+    } else if (text_mode == lcd_mode_menu) {
148
+        for (int i = 0; i < LCD_TEXT_LINES; i++) {
149
+            if ((menu_pre[i].length() > 0) || (menu_post[i].length() > 0)) {
150
+                lcd_scroll_multiline(text + i, 1, LCD_TEXT_WIDTH,
151
+                                     menu_pre[i], menu_post[i], menu_dir[i]);
152
+            }
153
+        }
154
+    }
155
+}
156
+
157
+int lcd_text_lines(void) {
158
+    return LCD_TEXT_LINES;
159
+}
160
+
20
 void lcd_init(void) {
161
 void lcd_init(void) {
21
 #ifdef USE_20X4_TEXT_LCD
162
 #ifdef USE_20X4_TEXT_LCD
22
     lcd.begin(20, 4);
163
     lcd.begin(20, 4);
28
     lcd.print(F(FIRMWARE_VERSION));
169
     lcd.print(F(FIRMWARE_VERSION));
29
     lcd.print(F("made by: xythobuz.de"));
170
     lcd.print(F("made by: xythobuz.de"));
30
 #endif // USE_20X4_TEXT_LCD
171
 #endif // USE_20X4_TEXT_LCD
172
+
173
+#ifdef USE_FULL_GRAPHIC_LCD
174
+    lcd.begin();
175
+
176
+    lcd.firstPage();
177
+    do {
178
+        lcd.setFont(u8g2_font_luBS12_tr);
179
+        lcd.drawStr(0, 14 * 1, "Fuellfix v2");
180
+        lcd.drawStr(0, 14 * 2, "Initializing");
181
+
182
+        lcd.setFont(u8g2_font_t0_12b_tr);
183
+        lcd.drawStr(0, 14 * 2 + 8 + 12 * 1, "Software Version " FIRMWARE_VERSION);
184
+        lcd.drawStr(0, 14 * 2 + 8 + 12 * 2, "made by: xythobuz.de");
185
+    } while (lcd.nextPage());
186
+#endif // USE_FULL_GRAPHIC_LCD
187
+}
188
+
189
+void lcd_loop(void) {
190
+    if ((millis() - last_scroll_time) >= SCROLL_DELAY) {
191
+        last_scroll_time = millis();
192
+        lcd_scrolling();
193
+    }
194
+
195
+#ifdef USE_FULL_GRAPHIC_LCD
196
+    if (redraw) {
197
+        lcd.firstPage();
198
+        do {
199
+            lcd.setFont(LCD_HEADING_FONT);
200
+            for (int i = 0; i < LCD_HEADING_LINES; i++) {
201
+                lcd.drawStr(0, LCD_HEADING_HEIGHT * (i + 1), heading[i].c_str());
202
+            }
203
+
204
+            lcd.setFont(LCD_TEXT_FONT);
205
+            for (int i = 0; i < LCD_TEXT_LINES; i++) {
206
+                lcd.drawStr(0, LCD_HEADING_HEIGHT * LCD_HEADING_LINES + LCD_HEADING_TEXT_OFFSET + LCD_TEXT_HEIGHT * (i + 1), text[i].c_str());
207
+            }
208
+        } while (lcd.nextPage());
209
+        redraw = false;
210
+    }
211
+#endif // USE_FULL_GRAPHIC_LCD
31
 }
212
 }
32
 
213
 
33
 void lcd_clear(void) {
214
 void lcd_clear(void) {
34
     Serial.println();
215
     Serial.println();
35
 
216
 
217
+    text_mode = lcd_mode_none;
218
+
36
 #ifdef USE_20X4_TEXT_LCD
219
 #ifdef USE_20X4_TEXT_LCD
37
     lcd.clear();
220
     lcd.clear();
38
 #endif // USE_20X4_TEXT_LCD
221
 #endif // USE_20X4_TEXT_LCD
222
+
223
+#ifdef USE_FULL_GRAPHIC_LCD
224
+    for (int i = 0; i < LCD_HEADING_LINES; i++) {
225
+        heading[i] = "";
226
+    }
227
+    for (int i = 0; i < LCD_TEXT_LINES; i++) {
228
+        text[i] = "";
229
+    }
230
+    redraw = true;
231
+#endif // USE_FULL_GRAPHIC_LCD
39
 }
232
 }
40
 
233
 
41
-void lcd_set_heading(const char *heading) {
42
-    Serial.println(heading);
234
+void lcd_set_heading(const char *h) {
235
+    Serial.println(h);
43
 
236
 
44
 #ifdef USE_20X4_TEXT_LCD
237
 #ifdef USE_20X4_TEXT_LCD
45
     lcd.setCursor(0, 0);
238
     lcd.setCursor(0, 0);
46
-    lcd.print(heading);
239
+    lcd.print(h);
47
 #endif // USE_20X4_TEXT_LCD
240
 #endif // USE_20X4_TEXT_LCD
241
+
242
+#ifdef USE_FULL_GRAPHIC_LCD
243
+    heading[0] = h;
244
+    heading_pre = "";
245
+    heading_direction = 0;
246
+    lcd_shorten_multiline(heading, LCD_HEADING_LINES, LCD_HEADING_WIDTH, &heading_post);
247
+    redraw = true;
248
+#endif // USE_FULL_GRAPHIC_LCD
249
+}
250
+
251
+void lcd_set_text(const char *t) {
252
+    Serial.println(t);
253
+
254
+    text_mode = lcd_mode_multiline;
255
+
256
+#ifdef USE_20X4_TEXT_LCD
257
+    lcd.setCursor(0, LCD_HEADING_LINES);
258
+    lcd.print(t);
259
+#endif // USE_20X4_TEXT_LCD
260
+
261
+#ifdef USE_FULL_GRAPHIC_LCD
262
+    text[0] = t;
263
+    text_pre = "";
264
+    text_direction = 0;
265
+    lcd_shorten_multiline(text, LCD_TEXT_LINES, LCD_TEXT_WIDTH, &text_post);
266
+    redraw = true;
267
+#endif // USE_FULL_GRAPHIC_LCD
48
 }
268
 }
49
 
269
 
50
-void lcd_set_text(const char *text) {
51
-    Serial.println(text);
270
+void lcd_set_menu_text(int line, const char *t) {
271
+    Serial.print(line);
272
+    Serial.print(": ");
273
+    Serial.println(t);
274
+
275
+    text_mode = lcd_mode_menu;
52
 
276
 
53
 #ifdef USE_20X4_TEXT_LCD
277
 #ifdef USE_20X4_TEXT_LCD
54
-    lcd.setCursor(0, 1);
55
-    lcd.print(text);
278
+    lcd.setCursor(0, LCD_HEADING_LINES + line);
279
+    lcd.print(t);
56
 #endif // USE_20X4_TEXT_LCD
280
 #endif // USE_20X4_TEXT_LCD
281
+
282
+#ifdef USE_FULL_GRAPHIC_LCD
283
+    text[line] = t;
284
+    menu_pre[line] = "";
285
+    menu_dir[line] = 0;
286
+    lcd_shorten_multiline(text + line, 1, LCD_TEXT_WIDTH, menu_post + line);
287
+    redraw = true;
288
+#endif // USE_FULL_GRAPHIC_LCD
57
 }
289
 }

+ 6
- 8
src/main.cpp View File

98
     Serial.println(F(" mm"));
98
     Serial.println(F(" mm"));
99
 
99
 
100
     Serial.print(F("\t"));
100
     Serial.print(F("\t"));
101
-    Serial.print(E_STEPS_PER_MM);
102
-    Serial.println(F(" steps/mm"));
101
+    Serial.print(E_STEPS_PER_PERCENT);
102
+    Serial.println(F(" steps/percent"));
103
 
103
 
104
     Serial.print(F("\t"));
104
     Serial.print(F("\t"));
105
     Serial.print(E_MAX_SPEED);
105
     Serial.print(E_MAX_SPEED);
106
-    Serial.println(F(" mm/s"));
106
+    Serial.println(F(" percent/s"));
107
 
107
 
108
     Serial.print(F("\t"));
108
     Serial.print(F("\t"));
109
     Serial.print(E_MAX_ACCEL);
109
     Serial.print(E_MAX_ACCEL);
110
-    Serial.println(F(" mm/s^2"));
110
+    Serial.println(F(" percent/s^2"));
111
 
111
 
112
     Serial.println();
112
     Serial.println();
113
 
113
 
136
     int click = encoder_click();
136
     int click = encoder_click();
137
     int kill = kill_switch();
137
     int kill = kill_switch();
138
 
138
 
139
-    if (click) {
140
-        async_beep(ENCODER_CLICK_BEEP_TIME, ENCODER_CLICK_BEEP_FREQ);
141
-    }
142
-
143
     struct StateMachineInput smi(click, encoder_change(), kill, !still_running);
139
     struct StateMachineInput smi(click, encoder_change(), kill, !still_running);
144
     states_run(smi);
140
     states_run(smi);
141
+
142
+    lcd_loop();
145
 }
143
 }

+ 223
- 13
src/statemachine.cpp View File

14
 // --------------------------------------
14
 // --------------------------------------
15
 
15
 
16
 StateText::StateText(State *_parent) : State(_parent) {
16
 StateText::StateText(State *_parent) : State(_parent) {
17
-    heading = "";
18
-    text = "";
17
+    heading = "no heading";
18
+    text = "text missing";
19
     onEnterFunc = []() { };
19
     onEnterFunc = []() { };
20
     whenInFunc = [](StateMachineInput smi) {
20
     whenInFunc = [](StateMachineInput smi) {
21
         State *s = states_get();
21
         State *s = states_get();
22
-        if (smi.click && (s != NULL) && (s->getChild() != NULL)) {
23
-            states_go_to(s->getChild());
22
+        if (smi.click && (s != NULL)) {
23
+            if (s->getChild() != NULL) {
24
+                states_go_to(s->getChild());
25
+            } else if (s->getParent() != NULL) {
26
+                states_go_to(s->getParent());
27
+            }
24
         }
28
         }
25
     };
29
     };
26
 }
30
 }
42
 }
46
 }
43
 
47
 
44
 void StateText::enterState(void) {
48
 void StateText::enterState(void) {
49
+    if (onEnterFunc != NULL) {
50
+        onEnterFunc();
51
+    }
52
+
45
     lcd_clear();
53
     lcd_clear();
46
     lcd_set_heading(heading);
54
     lcd_set_heading(heading);
47
     lcd_set_text(text);
55
     lcd_set_text(text);
48
-
49
-    onEnterFunc();
50
 }
56
 }
51
 
57
 
52
 void StateText::inState(struct StateMachineInput smi) {
58
 void StateText::inState(struct StateMachineInput smi) {
53
-    whenInFunc(smi);
59
+    if (whenInFunc != NULL) {
60
+        whenInFunc(smi);
61
+    }
54
 }
62
 }
55
 
63
 
56
 // --------------------------------------
64
 // --------------------------------------
57
 
65
 
58
-StateMenu::StateMenu(State *_parent) : State(_parent) {
66
+StateMenu::StateMenu(State *_parent, bool _show_parent) : State(_parent) {
67
+    show_parent = _show_parent;
59
     menuPos = 0;
68
     menuPos = 0;
69
+    menuOff = 0;
60
 }
70
 }
61
 
71
 
62
 void StateMenu::setChild(State *_child) {
72
 void StateMenu::setChild(State *_child) {
67
     if (pos < 0) {
77
     if (pos < 0) {
68
         setChild(_child);
78
         setChild(_child);
69
     } else {
79
     } else {
70
-        // TODO insert child at pos in children
80
+        array_insert_at_pos(&children, _child, pos);
71
     }
81
     }
72
 }
82
 }
73
 
83
 
74
 void StateMenu::enterState(void) {
84
 void StateMenu::enterState(void) {
75
-    menuPos = 0;
85
+    display();
86
+}
87
+
88
+void StateMenu::display(void) {
89
+    lcd_clear();
90
+    lcd_set_heading(getTitle());
91
+
92
+    int size = children.size();
93
+    if (show_parent) {
94
+        size++;
95
+    }
96
+
97
+    for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < size); i++) {
98
+        String s = "";
99
+        if (i == menuPos) {
100
+            s += "> ";
101
+        } else {
102
+            s += "  ";
103
+        }
104
+        if (i == children.size()) {
105
+            s += getParent()->getTitle();
106
+        } else {
107
+            s += children.at(i)->getTitle();
108
+        }
109
+        lcd_set_menu_text(i - menuOff, s.c_str());
110
+    }
76
 }
111
 }
77
 
112
 
78
 void StateMenu::inState(struct StateMachineInput smi) {
113
 void StateMenu::inState(struct StateMachineInput smi) {
114
+    int size = children.size();
115
+    if (show_parent) {
116
+        size++;
117
+    }
118
+
119
+    if (smi.encoder != 0) {
120
+        menuPos -= smi.encoder;
121
+
122
+        while (menuPos < 0) {
123
+            menuPos += size;
124
+        }
125
+
126
+        while (menuPos >= size) {
127
+            menuPos -= size;
128
+        }
79
 
129
 
130
+        while (menuPos < menuOff) {
131
+            menuOff--;
132
+        }
133
+
134
+        while (menuPos >= (menuOff + lcd_text_lines())) {
135
+            menuOff++;
136
+        }
137
+
138
+        display();
139
+    }
140
+
141
+    if (smi.click) {
142
+        if (menuPos == children.size()) {
143
+            menuPos = 0;
144
+            menuOff = 0;
145
+            states_go_to(getParent());
146
+        } else {
147
+            states_go_to(children.at(menuPos));
148
+        }
149
+    }
80
 }
150
 }
81
 
151
 
82
 // --------------------------------------
152
 // --------------------------------------
83
 
153
 
84
-StateDynamicMenu::StateDynamicMenu(State *_parent = NULL) : State(_parent) { }
154
+StateDynamicMenu::StateDynamicMenu(State *_parent) : State(_parent) {
155
+    menuPos = 0;
156
+    menuOff = 0;
157
+}
85
 
158
 
86
 void StateDynamicMenu::dataCount(CountFuncPtr count) {
159
 void StateDynamicMenu::dataCount(CountFuncPtr count) {
87
     countFunc = count;
160
     countFunc = count;
96
 }
169
 }
97
 
170
 
98
 void StateDynamicMenu::display(void) {
171
 void StateDynamicMenu::display(void) {
172
+    lcd_clear();
173
+    lcd_set_heading(getTitle());
99
 
174
 
175
+    for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < count + 1); i++) {
176
+        String s = "";
177
+        if (i == menuPos) {
178
+            s += "> ";
179
+        } else {
180
+            s += "  ";
181
+        }
182
+        if (i == count) {
183
+            s += getParent()->getTitle();
184
+        } else {
185
+            s += contents.at(i);
186
+        }
187
+        lcd_set_menu_text(i - menuOff, s.c_str());
188
+    }
100
 }
189
 }
101
 
190
 
102
 void StateDynamicMenu::enterState(void) {
191
 void StateDynamicMenu::enterState(void) {
103
     // cache all entries on entering state
192
     // cache all entries on entering state
104
-    count = countFunc();
193
+    if (countFunc != NULL) {
194
+        count = countFunc();
195
+    } else {
196
+        count = 0;
197
+    }
105
     contents.clear();
198
     contents.clear();
106
     for (int i = 0; i < count; i++) {
199
     for (int i = 0; i < count; i++) {
107
-        contents.push_back(getFunc(i));
200
+        if (getFunc != NULL) {
201
+            contents.push_back(getFunc(i));
202
+        } else {
203
+            contents.push_back("no get func");
204
+        }
108
     }
205
     }
109
 
206
 
110
     display();
207
     display();
111
 }
208
 }
112
 
209
 
113
 void StateDynamicMenu::inState(StateMachineInput smi) {
210
 void StateDynamicMenu::inState(StateMachineInput smi) {
211
+    if (smi.encoder != 0) {
212
+        menuPos -= smi.encoder;
213
+
214
+        while (menuPos < 0) {
215
+            menuPos += count + 1;
216
+        }
217
+
218
+        while (menuPos >= count + 1) {
219
+            menuPos -= count + 1;
220
+        }
221
+
222
+        while (menuPos < menuOff) {
223
+            menuOff--;
224
+        }
225
+
226
+        while (menuPos >= (menuOff + lcd_text_lines())) {
227
+            menuOff++;
228
+        }
229
+
230
+        display();
231
+    }
232
+
233
+    if (smi.click) {
234
+        if (menuPos == count) {
235
+            menuPos = 0;
236
+            menuOff = 0;
237
+            states_go_to(getParent());
238
+        } else {
239
+            if (callFunc != NULL) {
240
+                callFunc(menuPos);
241
+            }
242
+        }
243
+    }
244
+}
245
+
246
+// --------------------------------------
247
+
248
+template <typename T>
249
+StateValue<T>::StateValue(State *_parent, T &_value, T _min, T _max) : State(_parent), value(_value) {
250
+    min = _min;
251
+    max = _max;
252
+    updateFunc = NULL;
253
+}
254
+
255
+template <typename T>
256
+void StateValue<T>::onUpdate(UpdateFuncPtr func) {
257
+    updateFunc = func;
258
+}
259
+
260
+template <typename T>
261
+void StateValue<T>::display(void) {
262
+    String s = String(min) + " .. " + String(value) + " .. " + String(max);
263
+    lcd_set_text(s.c_str());
264
+}
265
+
266
+template <typename T>
267
+void StateValue<T>::enterState(void) {
268
+    lcd_clear();
269
+    lcd_set_heading(getTitle());
270
+
271
+    display();
272
+}
273
+
274
+template <typename T>
275
+void StateValue<T>::inState(StateMachineInput smi) {
276
+    if (smi.encoder != 0) {
277
+        value -= smi.encoder;
278
+        if (value < min) {
279
+            value = min;
280
+        }
281
+        if (value > max) {
282
+            value = max;
283
+        }
284
+        display();
285
+    }
286
+    if (smi.click) {
287
+        if (updateFunc != NULL) {
288
+            updateFunc(value);
289
+        }
290
+        states_go_to(getParent());
291
+    }
292
+}
293
+
294
+template class StateValue<float>;
295
+
296
+// --------------------------------------
297
+
298
+template <typename T, size_t N>
299
+void array_print(Array<T, N> *arr) {
300
+    Serial.print("Array length: ");
301
+    Serial.print(arr->size());
302
+    Serial.println(" contents:");
303
+    for (int i = 0; i < arr->size(); i++) {
304
+        Serial.print(i);
305
+        Serial.print(": ");
306
+        Serial.println(arr->at(i)->getTitle());
307
+    }
308
+}
309
+
310
+template <typename T, size_t N>
311
+void array_insert_at_pos(Array<T, N> *arr, T value, size_t pos) {
312
+    // make additional space
313
+    arr->push_back(value);
314
+
315
+    if ((pos >= arr->max_size()) || (pos >= arr->size())) {
316
+        // we can not shift it to the given position
317
+        return;
318
+    }
319
+
320
+    for (int i = arr->size() - 2; i >= pos; i--) {
321
+        arr->at(i + 1) = arr->at(i);
322
+    }
114
 
323
 
324
+    arr->at(pos) = value;
115
 }
325
 }

+ 141
- 14
src/states.cpp View File

13
 
13
 
14
 StateText sm_ask_homing = StateText();
14
 StateText sm_ask_homing = StateText();
15
 StateText sm_do_homing = StateText(&sm_ask_homing);
15
 StateText sm_do_homing = StateText(&sm_ask_homing);
16
-StateMenu sm_menu = StateMenu(&sm_do_homing);
16
+StateMenu sm_menu = StateMenu(&sm_do_homing, false);
17
 
17
 
18
 StateMenu sm_auto = StateMenu(&sm_menu);
18
 StateMenu sm_auto = StateMenu(&sm_menu);
19
 StateDynamicMenu sm_presets = StateDynamicMenu(&sm_auto);
19
 StateDynamicMenu sm_presets = StateDynamicMenu(&sm_auto);
20
-StateDynamicMenu sm_new_preset = StateDynamicMenu(&sm_auto);
20
+StateText sm_new_preset = StateText(&sm_auto);
21
 StateDynamicMenu sm_mod_preset = StateDynamicMenu(&sm_auto);
21
 StateDynamicMenu sm_mod_preset = StateDynamicMenu(&sm_auto);
22
 StateDynamicMenu sm_del_preset = StateDynamicMenu(&sm_auto);
22
 StateDynamicMenu sm_del_preset = StateDynamicMenu(&sm_auto);
23
 
23
 
24
-StateMenu sm_config = StateMenu(&sm_menu);
24
+StateMenu sm_move = StateMenu(&sm_menu);
25
+StateText sm_move_x = StateText(&sm_move);
26
+StateText sm_move_y = StateText(&sm_move);
27
+StateText sm_move_z = StateText(&sm_move);
28
+StateText sm_move_e = StateText(&sm_move);
25
 
29
 
30
+StateMenu sm_config = StateMenu(&sm_menu);
31
+StateText sm_conf_load = StateText(&sm_config);
32
+StateText sm_conf_save = StateText(&sm_config);
33
+StateValue<float> sm_conf_speed_xy = StateValue<float>(&sm_config, data_options()->speed_x, 1.0, XY_MAX_SPEED);
34
+StateValue<float> sm_conf_speed_z = StateValue<float>(&sm_config, data_options()->speed_z, 1.0, Z_MAX_SPEED);
35
+StateValue<float> sm_conf_speed_e = StateValue<float>(&sm_config, data_options()->speed_e, 1.0, E_MAX_SPEED);
36
+StateValue<float> sm_conf_accel_xy = StateValue<float>(&sm_config, data_options()->accel_x, 1.0, XY_MAX_ACCEL);
37
+StateValue<float> sm_conf_accel_z = StateValue<float>(&sm_config, data_options()->accel_z, 1.0, Z_MAX_ACCEL);
38
+StateValue<float> sm_conf_accel_e = StateValue<float>(&sm_config, data_options()->accel_e, 1.0, E_MAX_ACCEL);
26
 
39
 
27
 // --------------------------------------
40
 // --------------------------------------
28
 
41
 
29
 State *current_state = NULL;
42
 State *current_state = NULL;
43
+String strbuf;
30
 
44
 
31
 void states_init(void) {
45
 void states_init(void) {
32
     // ----------------------------------
46
     // ----------------------------------
33
 
47
 
48
+    sm_ask_homing.setTitle("Ask for homing");
34
     sm_ask_homing.setHeading("Homing Required!");
49
     sm_ask_homing.setHeading("Homing Required!");
35
     sm_ask_homing.setText("Click to home all four axes.");
50
     sm_ask_homing.setText("Click to home all four axes.");
36
 
51
 
37
     // ----------------------------------
52
     // ----------------------------------
38
 
53
 
39
     sm_do_homing.setTitle("Home all axes");
54
     sm_do_homing.setTitle("Home all axes");
40
-    sm_do_homing.setHeading("Homing");
55
+    sm_do_homing.setHeading("Homing...");
41
 
56
 
42
     sm_do_homing.onEnter([]() {
57
     sm_do_homing.onEnter([]() {
43
-        steppers_start_homing();
58
+        //steppers_start_homing();
44
     });
59
     });
45
 
60
 
46
     sm_do_homing.whenIn([](StateMachineInput smi) {
61
     sm_do_homing.whenIn([](StateMachineInput smi) {
47
-        if (smi.motors_done) {
48
-            if (steppers_homed()) {
49
-                async_beep(100, 2000);
62
+        //if (smi.motors_done) {
63
+        //    if (steppers_homed()) {
64
+                async_beep(HOMING_BEEP_TIME, HOMING_BEEP_FREQ);
50
                 states_go_to(&sm_menu);
65
                 states_go_to(&sm_menu);
51
-            }
52
-        }
66
+        //    }
67
+        //}
53
 
68
 
54
         // TODO update text with current axis
69
         // TODO update text with current axis
55
     });
70
     });
61
 
76
 
62
     // ----------------------------------
77
     // ----------------------------------
63
 
78
 
79
+    sm_move.setTitle("Move Axis");
80
+
81
+    sm_move_x.setTitle("X Axis");
82
+    sm_move_y.setTitle("Y Axis");
83
+    sm_move_z.setTitle("Z Axis");
84
+    sm_move_e.setTitle("E Axis");
85
+
86
+    // ----------------------------------
87
+
64
     sm_auto.setTitle("Filling Menu");
88
     sm_auto.setTitle("Filling Menu");
65
-    sm_auto.setChild(&sm_menu);
66
 
89
 
67
-    sm_presets.setTitle("Presets");
90
+    sm_presets.setTitle("Use Preset");
68
     sm_presets.dataCount([]() {
91
     sm_presets.dataCount([]() {
69
         return (int)data_preset_count();
92
         return (int)data_preset_count();
70
     });
93
     });
73
         // dynamically. need to have a name stored
96
         // dynamically. need to have a name stored
74
         // somewhere, in data/eeprom, for each preset
97
         // somewhere, in data/eeprom, for each preset
75
         // that we can pass here
98
         // that we can pass here
99
+        return "foo";
100
+    });
101
+
102
+    sm_new_preset.setTitle("Add new Preset");
103
+    sm_new_preset.setHeading("Add new Preset");
104
+    sm_new_preset.onEnter([]() {
105
+        struct data_config_preset preset;
106
+        if (!data_preset_add(preset)) {
107
+            strbuf = String(data_eeprom_error()) + " Error adding preset!";
108
+            sm_new_preset.setText(strbuf.c_str());
109
+        } else {
110
+            strbuf = "Preset " + String(data_preset_count()) + " has been added!";
111
+            sm_new_preset.setText(strbuf.c_str());
112
+        }
76
     });
113
     });
77
 
114
 
78
-    sm_new_preset.setTitle("New Preset");
79
     sm_mod_preset.setTitle("Modify Preset");
115
     sm_mod_preset.setTitle("Modify Preset");
116
+    sm_mod_preset.dataCount([]() {
117
+        return (int)data_preset_count();
118
+    });
119
+    sm_mod_preset.dataGet([](int i) {
120
+        // TODO can not build a name string here
121
+        // dynamically. need to have a name stored
122
+        // somewhere, in data/eeprom, for each preset
123
+        // that we can pass here
124
+        return "foo";
125
+    });
126
+
80
     sm_del_preset.setTitle("Delete Preset");
127
     sm_del_preset.setTitle("Delete Preset");
128
+    sm_del_preset.dataCount([]() {
129
+        return (int)data_preset_count();
130
+    });
131
+    sm_del_preset.dataGet([](int i) {
132
+        // TODO can not build a name string here
133
+        // dynamically. need to have a name stored
134
+        // somewhere, in data/eeprom, for each preset
135
+        // that we can pass here
136
+        return "foo";
137
+    });
81
 
138
 
82
     // ----------------------------------
139
     // ----------------------------------
83
 
140
 
84
     sm_config.setTitle("Configuration");
141
     sm_config.setTitle("Configuration");
85
-    sm_auto.setChild(&sm_menu);
142
+
143
+    sm_conf_load.setTitle("Load from EEPROM");
144
+    sm_conf_load.setHeading("Load from EEPROM");
145
+    sm_conf_load.onEnter([]() {
146
+        if (!data_eeprom_read()) {
147
+            strbuf = String(data_eeprom_error()) + " Error reading configuration!";
148
+            sm_conf_load.setText(strbuf.c_str());
149
+        } else {
150
+            sm_conf_load.setText("Configuration read successful!");
151
+
152
+            steppers_set_speed_x(data_options()->speed_x);
153
+            steppers_set_accel_x(data_options()->accel_x);
154
+            steppers_set_speed_y(data_options()->speed_y);
155
+            steppers_set_accel_y(data_options()->accel_y);
156
+            steppers_set_speed_z(data_options()->speed_z);
157
+            steppers_set_accel_z(data_options()->accel_z);
158
+            steppers_set_speed_e(data_options()->speed_e);
159
+            steppers_set_accel_e(data_options()->accel_e);
160
+        }
161
+    });
162
+
163
+    sm_conf_save.setTitle("Store to EEPROM");
164
+    sm_conf_save.setHeading("Store to EEPROM");
165
+    sm_conf_save.setText("Configuration written to EEPROM!");
166
+    sm_conf_save.onEnter([]() {
167
+        data_eeprom_write();
168
+    });
169
+
170
+    sm_conf_speed_xy.setTitle("XY Speed");
171
+    sm_conf_speed_xy.onUpdate([](float v) {
172
+        steppers_set_speed_x(v);
173
+        steppers_set_speed_y(v);
174
+    });
175
+
176
+    sm_conf_speed_z.setTitle("Z Speed");
177
+    sm_conf_speed_z.onUpdate([](float v) {
178
+        steppers_set_speed_z(v);
179
+    });
180
+
181
+    sm_conf_speed_e.setTitle("E Speed");
182
+    sm_conf_speed_e.onUpdate([](float v) {
183
+        steppers_set_speed_e(v);
184
+    });
185
+
186
+    sm_conf_accel_xy.setTitle("XY Acceleration");
187
+    sm_conf_accel_xy.onUpdate([](float v) {
188
+        steppers_set_accel_x(v);
189
+        steppers_set_accel_y(v);
190
+    });
191
+
192
+    sm_conf_accel_z.setTitle("Z Acceleration");
193
+    sm_conf_accel_z.onUpdate([](float v) {
194
+        steppers_set_accel_z(v);
195
+    });
196
+
197
+    sm_conf_accel_e.setTitle("E Acceleration");
198
+    sm_conf_accel_e.onUpdate([](float v) {
199
+        steppers_set_accel_e(v);
200
+    });
86
 
201
 
87
     // ----------------------------------
202
     // ----------------------------------
88
 
203
 
90
 }
205
 }
91
 
206
 
92
 void states_run(StateMachineInput smi) {
207
 void states_run(StateMachineInput smi) {
208
+    if (smi.click) {
209
+        async_beep(ENCODER_CLICK_BEEP_TIME, ENCODER_CLICK_BEEP_FREQ);
210
+    }
211
+
212
+    if (smi.kill) {
213
+        steppers_kill();
214
+        Serial.println("Kill button pressed!");
215
+        blocking_beep(KILL_BEEP_TIME, KILL_BEEP_FREQ, KILL_BEEP_REPEAT - 1);
216
+        states_go_to(&sm_ask_homing);
217
+        return;
218
+    }
219
+
93
     if (current_state != NULL) {
220
     if (current_state != NULL) {
94
         current_state->inState(smi);
221
         current_state->inState(smi);
95
     }
222
     }

+ 119
- 17
src/steppers.cpp View File

4
 #include "config.h"
4
 #include "config.h"
5
 #include "config_pins.h"
5
 #include "config_pins.h"
6
 #include "lcd.h"
6
 #include "lcd.h"
7
+#include "data.h"
7
 #include "steppers.h"
8
 #include "steppers.h"
8
 
9
 
9
 static AccelStepper stepper_x(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN, 0, 0, false);
10
 static AccelStepper stepper_x(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN, 0, 0, false);
33
 static unsigned long steppers_home_move_start_time = 0;
34
 static unsigned long steppers_home_move_start_time = 0;
34
 
35
 
35
 void steppers_init(void) {
36
 void steppers_init(void) {
36
-    pinMode(X_ENDSTOP_PIN, INPUT);
37
-    pinMode(Y_ENDSTOP_PIN, INPUT);
38
-    pinMode(Z_ENDSTOP_PIN, INPUT);
39
-    pinMode(E_ENDSTOP_PIN, INPUT);
37
+    pinMode(X_ENDSTOP_PIN, INPUT_PULLUP);
38
+    pinMode(Y_ENDSTOP_PIN, INPUT_PULLUP);
39
+    pinMode(Z_ENDSTOP_PIN, INPUT_PULLUP);
40
+    pinMode(E_ENDSTOP_PIN, INPUT_PULLUP);
40
 
41
 
41
     pinMode(X_ENABLE_PIN, OUTPUT);
42
     pinMode(X_ENABLE_PIN, OUTPUT);
42
     pinMode(X_STEP_PIN, OUTPUT);
43
     pinMode(X_STEP_PIN, OUTPUT);
53
 
54
 
54
     stepper_x.setEnablePin(X_ENABLE_PIN);
55
     stepper_x.setEnablePin(X_ENABLE_PIN);
55
     stepper_x.setMaxSpeed(XY_MAX_SPEED * XY_STEPS_PER_MM);
56
     stepper_x.setMaxSpeed(XY_MAX_SPEED * XY_STEPS_PER_MM);
56
-    stepper_x.setAcceleration(XY_MAX_ACCEL * XY_STEPS_PER_MM);
57
+    steppers_set_speed_x(data_options()->speed_x);
58
+    steppers_set_accel_x(data_options()->accel_x);
57
 
59
 
58
     stepper_y.setEnablePin(Y_ENABLE_PIN);
60
     stepper_y.setEnablePin(Y_ENABLE_PIN);
59
-    stepper_y.setMaxSpeed(XY_MAX_SPEED * XY_STEPS_PER_MM);
60
-    stepper_y.setAcceleration(XY_MAX_ACCEL * XY_STEPS_PER_MM);
61
+    steppers_set_speed_y(data_options()->speed_y);
62
+    steppers_set_accel_y(data_options()->accel_y);
61
 
63
 
62
     stepper_z.setEnablePin(Z_ENABLE_PIN);
64
     stepper_z.setEnablePin(Z_ENABLE_PIN);
63
-    stepper_z.setMaxSpeed(Z_MAX_SPEED * Z_STEPS_PER_MM);
64
-    stepper_z.setAcceleration(Z_MAX_ACCEL * Z_STEPS_PER_MM);
65
+    steppers_set_speed_z(data_options()->speed_z);
66
+    steppers_set_accel_z(data_options()->accel_z);
65
 
67
 
66
     stepper_e.setEnablePin(E0_ENABLE_PIN);
68
     stepper_e.setEnablePin(E0_ENABLE_PIN);
67
-    stepper_e.setMaxSpeed(E_MAX_SPEED * E_STEPS_PER_MM);
68
-    stepper_e.setAcceleration(E_MAX_ACCEL * E_STEPS_PER_MM);
69
+    steppers_set_speed_e(data_options()->speed_e);
70
+    steppers_set_accel_e(data_options()->accel_e);
69
 }
71
 }
70
 
72
 
71
 static void steppers_initiate_home(int axis, int phase) {
73
 static void steppers_initiate_home(int axis, int phase) {
111
         // e
113
         // e
112
         if (phase == 0) {
114
         if (phase == 0) {
113
             state = step_homing_e_fast;
115
             state = step_homing_e_fast;
114
-            stepper_e.setSpeed(E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_FAST_HOME_SPEED * E_STEPS_PER_MM);
116
+            stepper_e.setSpeed(E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_FAST_HOME_SPEED * E_STEPS_PER_PERCENT);
115
         } else if (phase == 1) {
117
         } else if (phase == 1) {
116
             state = step_homing_e_back;
118
             state = step_homing_e_back;
117
-            stepper_e.setSpeed(-1.0 * E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_FAST_HOME_SPEED * E_STEPS_PER_MM);
119
+            stepper_e.setSpeed(-1.0 * E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_FAST_HOME_SPEED * E_STEPS_PER_PERCENT);
118
         } else if (phase == 2) {
120
         } else if (phase == 2) {
119
             state = step_homing_e_slow;
121
             state = step_homing_e_slow;
120
-            stepper_e.setSpeed(E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_SLOW_HOME_SPEED * E_STEPS_PER_MM);
122
+            stepper_e.setSpeed(E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_SLOW_HOME_SPEED * E_STEPS_PER_PERCENT);
121
         }
123
         }
122
     } else {
124
     } else {
123
         Serial.println(F("home_init error: invalid axis"));
125
         Serial.println(F("home_init error: invalid axis"));
155
         }
157
         }
156
     } else if (state == step_homing_x_slow) {
158
     } else if (state == step_homing_x_slow) {
157
         if (steppers_home_switch(0)) {
159
         if (steppers_home_switch(0)) {
160
+            stepper_x.setSpeed(0);
158
             steppers_initiate_home(1, 0);
161
             steppers_initiate_home(1, 0);
159
         } else {
162
         } else {
160
             stepper_x.runSpeed();
163
             stepper_x.runSpeed();
174
         }
177
         }
175
     } else if (state == step_homing_y_slow) {
178
     } else if (state == step_homing_y_slow) {
176
         if (steppers_home_switch(1)) {
179
         if (steppers_home_switch(1)) {
180
+            stepper_y.setSpeed(0);
177
             steppers_initiate_home(3, 0);
181
             steppers_initiate_home(3, 0);
178
         } else {
182
         } else {
179
             stepper_y.runSpeed();
183
             stepper_y.runSpeed();
193
         }
197
         }
194
     } else if (state == step_homing_z_slow) {
198
     } else if (state == step_homing_z_slow) {
195
         if (steppers_home_switch(2)) {
199
         if (steppers_home_switch(2)) {
200
+            stepper_z.setSpeed(0);
196
             steppers_initiate_home(0, 0);
201
             steppers_initiate_home(0, 0);
197
         } else {
202
         } else {
198
             stepper_z.runSpeed();
203
             stepper_z.runSpeed();
212
         }
217
         }
213
     } else if (state == step_homing_e_slow) {
218
     } else if (state == step_homing_e_slow) {
214
         if (steppers_home_switch(3)) {
219
         if (steppers_home_switch(3)) {
220
+            stepper_e.setSpeed(0);
215
             state = step_homed;
221
             state = step_homed;
216
             return false;
222
             return false;
217
         } else {
223
         } else {
218
-            stepper_z.runSpeed();
224
+            stepper_e.runSpeed();
219
         }
225
         }
220
     } else if (state != step_disabled) {
226
     } else if (state != step_disabled) {
221
         for (int i = 0; i < 4; i++) {
227
         for (int i = 0; i < 4; i++) {
332
     Serial.print(F("Moving E to "));
338
     Serial.print(F("Moving E to "));
333
     Serial.print(pos);
339
     Serial.print(pos);
334
     Serial.print(F(" mm ("));
340
     Serial.print(F(" mm ("));
335
-    Serial.print(pos * E_STEPS_PER_MM * E_AXIS_MOVEMENT_DIR);
341
+    Serial.print(E_MM_TO_PERCENT(pos));
342
+    Serial.println(F("% = "));
343
+    Serial.print(E_MM_TO_PERCENT(pos) * E_STEPS_PER_PERCENT * E_AXIS_MOVEMENT_DIR);
336
     Serial.println(F(" steps)"));
344
     Serial.println(F(" steps)"));
337
 
345
 
338
     if (pos < E_AXIS_MIN) {
346
     if (pos < E_AXIS_MIN) {
345
         return -1;
353
         return -1;
346
     }
354
     }
347
 
355
 
348
-    return steppers_move_axis(stepper_e, pos * E_STEPS_PER_MM * E_AXIS_MOVEMENT_DIR);
356
+    return steppers_move_axis(stepper_e, E_MM_TO_PERCENT(pos) * E_STEPS_PER_PERCENT * E_AXIS_MOVEMENT_DIR);
357
+}
358
+
359
+void steppers_kill(void) {
360
+    stepper_x.setCurrentPosition(0);
361
+    stepper_y.setCurrentPosition(0);
362
+    stepper_z.setCurrentPosition(0);
363
+    stepper_e.setCurrentPosition(0);
364
+
365
+    stepper_x.disableOutputs();
366
+    stepper_y.disableOutputs();
367
+    stepper_z.disableOutputs();
368
+    stepper_e.disableOutputs();
369
+
370
+    state = step_not_homed;
371
+}
372
+
373
+void steppers_set_speed_x(float speed) {
374
+    if (speed < 0.0) {
375
+        speed = 0.0;
376
+    }
377
+    if (speed > XY_MAX_SPEED) {
378
+        speed = XY_MAX_SPEED;
379
+    }
380
+    stepper_x.setMaxSpeed(speed * XY_STEPS_PER_MM);
381
+}
382
+
383
+void steppers_set_speed_y(float speed) {
384
+    if (speed < 0.0) {
385
+        speed = 0.0;
386
+    }
387
+    if (speed > XY_MAX_SPEED) {
388
+        speed = XY_MAX_SPEED;
389
+    }
390
+    stepper_y.setMaxSpeed(speed * XY_STEPS_PER_MM);
391
+}
392
+
393
+void steppers_set_speed_z(float speed) {
394
+    if (speed < 0.0) {
395
+        speed = 0.0;
396
+    }
397
+    if (speed > Z_MAX_SPEED) {
398
+        speed = Z_MAX_SPEED;
399
+    }
400
+    stepper_z.setMaxSpeed(speed * Z_STEPS_PER_MM);
401
+}
402
+
403
+void steppers_set_speed_e(float speed) {
404
+    if (speed < 0.0) {
405
+        speed = 0.0;
406
+    }
407
+    if (speed > E_MAX_SPEED) {
408
+        speed = E_MAX_SPEED;
409
+    }
410
+    stepper_e.setMaxSpeed(speed * E_STEPS_PER_PERCENT);
411
+}
412
+
413
+void steppers_set_accel_x(float accel) {
414
+    if (accel < 0.0) {
415
+        accel = 0.0;
416
+    }
417
+    if (accel > XY_MAX_ACCEL) {
418
+        accel = XY_MAX_ACCEL;
419
+    }
420
+    stepper_x.setAcceleration(accel * XY_STEPS_PER_MM);
421
+}
422
+
423
+void steppers_set_accel_y(float accel) {
424
+    if (accel < 0.0) {
425
+        accel = 0.0;
426
+    }
427
+    if (accel > XY_MAX_ACCEL) {
428
+        accel = XY_MAX_ACCEL;
429
+    }
430
+    stepper_y.setAcceleration(accel * XY_STEPS_PER_MM);
431
+}
432
+
433
+void steppers_set_accel_z(float accel) {
434
+    if (accel < 0.0) {
435
+        accel = 0.0;
436
+    }
437
+    if (accel > Z_MAX_ACCEL) {
438
+        accel = Z_MAX_ACCEL;
439
+    }
440
+    stepper_z.setAcceleration(accel * Z_STEPS_PER_MM);
441
+}
442
+
443
+void steppers_set_accel_e(float accel) {
444
+    if (accel < 0.0) {
445
+        accel = 0.0;
446
+    }
447
+    if (accel > E_MAX_ACCEL) {
448
+        accel = E_MAX_ACCEL;
449
+    }
450
+    stepper_e.setAcceleration(accel * E_STEPS_PER_PERCENT);
349
 }
451
 }

Loading…
Cancel
Save