Преглед на файлове

whole lot of firmware work. xy table now basically usable.

Thomas Buck преди 3 години
родител
ревизия
924921ebdd
променени са 17 файла, в които са добавени 1180 реда и са изтрити 791 реда
  1. 3
    1
      include/common.h
  2. 20
    6
      include/config.h
  3. 8
    8
      include/config_pins.h
  4. 22
    5
      include/data.h
  5. 9
    2
      include/encoder.h
  6. 25
    45
      include/statemachine.h
  7. 1
    1
      include/states.h
  8. 2
    1
      include/steppers.h
  9. 15
    2
      src/common.cpp
  10. 33
    17
      src/data.cpp
  11. 32
    28
      src/encoder.cpp
  12. 74
    17
      src/main.cpp
  13. 225
    0
      src/sm_menu.cpp
  14. 239
    0
      src/sm_value.cpp
  15. 8
    498
      src/statemachine.cpp
  16. 275
    32
      src/states.cpp
  17. 189
    128
      src/steppers.cpp

+ 3
- 1
include/common.h Целия файл

@@ -3,9 +3,11 @@
3 3
 
4 4
 #define CLEAR_STORE_INTERRUPTS() uint8_t prev_int_reg = SREG; cli()
5 5
 #define RESTORE_INTERRUPTS() SREG = prev_int_reg
6
+//#define CLEAR_STORE_INTERRUPTS() cli()
7
+//#define RESTORE_INTERRUPTS() sei()
6 8
 
7 9
 void async_beep(int time, int freq);
8 10
 void blocking_beep(int time, int freq, int repeat = 0);
9
-void common_run(unsigned long t);
11
+void common_run(void);
10 12
 
11 13
 #endif // _COMMON_H_

+ 20
- 6
include/config.h Целия файл

@@ -24,6 +24,12 @@
24 24
  ********** Hardware Settings **********
25 25
  ***************************************/
26 26
 
27
+#define AXIS_COUNT 4
28
+#define X_AXIS 0
29
+#define Y_AXIS 1
30
+#define Z_AXIS 2
31
+#define E_AXIS 3
32
+
27 33
 // xy steps per mm
28 34
 #define XY_BELT_PITCH 2.0
29 35
 #define XY_PULLEY_TEETH 40.0
@@ -67,9 +73,9 @@
67 73
 #define E_MM_TO_PERCENT(x) ((acos((x * 2.0 / E_AXIS_MAX) - 1.0) - PI) * 100.0 / PI)
68 74
 
69 75
 // maximum speeds
70
-#define XY_MAX_SPEED 50.0 // in mm/s
71
-#define Z_MAX_SPEED 20.0 // in mm/s
72
-#define E_MAX_SPEED 50.0 // in percent/s
76
+#define XY_MAX_SPEED 50.0 // in mm/s --> 50mm/s = 2000steps/s
77
+#define Z_MAX_SPEED 1.2 // in mm/s --> 20mm/s = 32000steps/s
78
+#define E_MAX_SPEED 30.0 // in percent/s --> 50%/s = 2400steps/s
73 79
 
74 80
 // homing speeds
75 81
 #define XY_FAST_HOME_SPEED 25.0 // in mm/s
@@ -100,11 +106,19 @@
100 106
 #define E_HOME_BACK_OFF_TIME (E_BACK_OFF_DISTANCE / E_FAST_HOME_SPEED * 1000)
101 107
 
102 108
 // epsilon around expected endstop position where we dont abort on hits
103
-#define X_AXIS_EPSILON 20.0 // TODO
104
-#define Y_AXIS_EPSILON 20.0 // TODO
109
+// if you need to increase this value, try to reduce play in your axis
110
+#define X_AXIS_EPSILON 1.0
111
+#define Y_AXIS_EPSILON 1.0
105 112
 #define Z_AXIS_EPSILON 1.0
106 113
 #define E_AXIS_EPSILON 1.0
107 114
 
108
-#define ENCODER_RPM_VALUE_FACTOR 10.0
115
+#define ENCODER_RPM_VALUE_FACTOR 2.0
116
+#define IDLE_TIMEOUT (5UL * 60UL * 1000UL) // ms, 0 to disable
117
+
118
+// TimerOne freq for steppers
119
+#define XY_MAX_HZ (XY_MAX_SPEED * XY_STEPS_PER_MM)
120
+#define Z_MAX_HZ (Z_MAX_SPEED * Z_STEPS_PER_MM)
121
+#define E_MAX_HZ (E_MAX_SPEED * E_STEPS_PER_PERCENT)
122
+#define MAX_SAMPLE_FREQ 2500
109 123
 
110 124
 #endif // _CONFIG_H_

+ 8
- 8
include/config_pins.h Целия файл

@@ -120,34 +120,34 @@
120 120
 #endif
121 121
 
122 122
 #if (X_MIN_PIN == -1)
123
-#define X_HOMING_DIR 1.0
123
+#define X_HOMING_DIR 1
124 124
 #define X_ENDSTOP_PIN X_MAX_PIN
125 125
 #else
126
-#define X_HOMING_DIR -1.0
126
+#define X_HOMING_DIR -1
127 127
 #define X_ENDSTOP_PIN X_MIN_PIN
128 128
 #endif
129 129
 
130 130
 #if (Y_MIN_PIN == -1)
131
-#define Y_HOMING_DIR 1.0
131
+#define Y_HOMING_DIR 1
132 132
 #define Y_ENDSTOP_PIN Y_MAX_PIN
133 133
 #else
134
-#define Y_HOMING_DIR -1.0
134
+#define Y_HOMING_DIR -1
135 135
 #define Y_ENDSTOP_PIN Y_MIN_PIN
136 136
 #endif
137 137
 
138 138
 #if (Z_MIN_PIN == -1)
139
-#define Z_HOMING_DIR 1.0
139
+#define Z_HOMING_DIR 1
140 140
 #define Z_ENDSTOP_PIN Z_MAX_PIN
141 141
 #else
142
-#define Z_HOMING_DIR -1.0
142
+#define Z_HOMING_DIR -1
143 143
 #define Z_ENDSTOP_PIN Z_MIN_PIN
144 144
 #endif
145 145
 
146 146
 #if (E_MIN_PIN == -1)
147
-#define E_HOMING_DIR 1.0
147
+#define E_HOMING_DIR 1
148 148
 #define E_ENDSTOP_PIN E_MAX_PIN
149 149
 #else
150
-#define E_HOMING_DIR -1.0
150
+#define E_HOMING_DIR -1
151 151
 #define E_ENDSTOP_PIN E_MIN_PIN
152 152
 #endif
153 153
 

+ 22
- 5
include/data.h Целия файл

@@ -1,22 +1,39 @@
1 1
 #ifndef _DATA_H_
2 2
 #define _DATA_H_
3 3
 
4
-#define DATA_SCHEMA_VERSION 0
4
+#define DATA_SCHEMA_VERSION 1
5 5
 
6 6
 struct data_config_options {
7
+    // in mm/s (%/s for e)
7 8
     float speed_x, speed_y, speed_z, speed_e;
9
+
10
+    // in mm/s^2 (%/s^2 for e)
8 11
     float accel_x, accel_y, accel_z, accel_e;
9 12
 };
10 13
 
11 14
 struct data_config_preset {
15
+    // number of containers
12 16
     uint8_t count_x, count_y;
13
-    float distance_x, distance_y;
14
-    float offset_x, offset_y;
15
-    float top_z, bottom_z;
16
-    float extrusion;
17
+
18
+    // distance between containers
19
+    float distance_x, distance_y; // in mm
20
+
21
+    // offset of first container
22
+    float offset_x, offset_y; // in mm
23
+
24
+    // height for moves between extrusions
25
+    float move_z; // in mm
26
+
27
+    // height while extruding
28
+    float bottom_z, top_z; // in mm
29
+
30
+    float extrusion_length; // in mm
31
+    float extrusion_bottom_wait; // in s
32
+    float extrusion_top_wait; // in s
17 33
 };
18 34
 
19 35
 void data_init(void);
36
+void data_clear(void);
20 37
 void data_eeprom_write(void);
21 38
 
22 39
 bool data_eeprom_read(void);

+ 9
- 2
include/encoder.h Целия файл

@@ -2,11 +2,18 @@
2 2
 #define _ENCODER_H_
3 3
 
4 4
 void encoder_init(void);
5
+
5 6
 void encoder_run(void);
6 7
 
8
+bool encoder_click(void);
9
+bool kill_switch(void);
10
+
11
+// --------------------------------------
12
+
13
+void encoder_run_fast(void);
14
+
15
+// disable interrupts while reading these
7 16
 int encoder_change(void);
8 17
 int encoder_rpm(void);
9
-int encoder_click(void);
10
-int kill_switch(void);
11 18
 
12 19
 #endif // _ENCODER_H_

+ 25
- 45
include/statemachine.h Целия файл

@@ -5,25 +5,27 @@
5 5
 
6 6
 #define STATE_ARRAY_SIZE 42
7 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
-
14 8
 struct StateMachineInput {
15
-    StateMachineInput(int c, int e, int r, int k, int m)
16
-            : click(c), encoder(e), rpm(r), kill(k), motors_done(m) { };
17
-
18
-    int click;
9
+    StateMachineInput(bool c, int e, int r, bool k, bool *m, bool am)
10
+            : click(c), encoder(e), rpm(r), kill(k), all_motors_done(am) {
11
+        for (int i = 0; i < AXIS_COUNT; i++) {
12
+            motor_done[i] = m[i];
13
+        }
14
+    };
15
+
16
+    bool click;
19 17
     int encoder;
20 18
     int rpm;
21
-    int kill;
22
-    int motors_done;
19
+    bool kill;
20
+    bool motor_done[AXIS_COUNT];
21
+    bool all_motors_done;
23 22
 };
24 23
 
25 24
 class State {
26 25
 public:
26
+    typedef void(*EnterFuncPtr)(void);
27
+    typedef void(*InFuncPtr)(StateMachineInput smi);
28
+
27 29
     State(State *_parent = NULL);
28 30
     State *getParent(void) { return parent; }
29 31
 
@@ -33,34 +35,24 @@ public:
33 35
     void setTitle(const char *_title) { title = _title; }
34 36
     const char *getTitle(void) { return title; }
35 37
 
36
-    virtual void enterState(void) = 0;
37
-    virtual void inState(StateMachineInput smi) = 0;
38
-
39
-private:
40
-    State *parent;
41
-    State *child;
42
-    const char *title;
43
-};
44
-
45
-class StateText : public State {
46
-public:
47
-    StateText(State *_parent = NULL);
48
-
49
-    void setHeading(const char *_heading);
50
-    void setText(const char *_text);
38
+    void setHeading(const char *_heading) { heading = _heading; }
39
+    const char *getHeading(void) { return heading; }
51 40
 
52
-    typedef void(*EnterFuncPtr)(void);
53
-    typedef void(*InFuncPtr)(StateMachineInput smi);
41
+    void setText(const char *_text) { text = _text; }
42
+    const char *getText(void) { return text; }
54 43
 
55
-    void onEnter(EnterFuncPtr func);
56
-    void whenIn(InFuncPtr func);
44
+    void onEnter(EnterFuncPtr func) { onEnterFunc = func; }
45
+    void whenIn(InFuncPtr func) { whenInFunc = func; }
57 46
 
58 47
     void updateText(void);
59 48
 
60 49
     virtual void enterState(void);
61 50
     virtual void inState(StateMachineInput smi);
62 51
 
63
-private:
52
+protected:
53
+    State *parent;
54
+    State *child;
55
+    const char *title;
64 56
     const char *heading;
65 57
     const char *text;
66 58
     EnterFuncPtr onEnterFunc;
@@ -120,13 +112,10 @@ class StateValue : public State {
120 112
 public:
121 113
     StateValue(State *_parent, T &_value, T _min, T _max);
122 114
 
123
-    void setHeading(const char *_heading);
124
-    void setText(const char *_text);
115
+    void setMax(T _max);
125 116
 
126
-    typedef void(*EnterFuncPtr)(void);
127 117
     typedef void(*UpdateFuncPtr)(T value);
128 118
 
129
-    void onEnter(EnterFuncPtr func);
130 119
     void onLiveUpdate(UpdateFuncPtr func);
131 120
     void onUpdate(UpdateFuncPtr func);
132 121
 
@@ -138,9 +127,6 @@ private:
138 127
 
139 128
     T &value;
140 129
     T min, max;
141
-    const char *heading;
142
-    const char *text;
143
-    EnterFuncPtr onEnterFunc;
144 130
     UpdateFuncPtr updateFunc, updateLiveFunc;
145 131
 };
146 132
 
@@ -151,13 +137,8 @@ public:
151 137
 
152 138
     void setData(size_t index, const char *name, T *value, T min, T max);
153 139
 
154
-    void setHeading(const char *_heading);
155
-    void setText(const char *_text);
156
-
157
-    typedef void(*EnterFuncPtr)(void);
158 140
     typedef void(*UpdateFuncPtr)(size_t index, T value);
159 141
 
160
-    void onEnter(EnterFuncPtr func);
161 142
     void onLiveUpdate(UpdateFuncPtr func);
162 143
     void onUpdate(UpdateFuncPtr func);
163 144
 
@@ -173,7 +154,6 @@ private:
173 154
     const char *heading;
174 155
     size_t pos;
175 156
     bool editing;
176
-    EnterFuncPtr onEnterFunc;
177 157
     UpdateFuncPtr updateFunc, updateLiveFunc;
178 158
 };
179 159
 

+ 1
- 1
include/states.h Целия файл

@@ -9,6 +9,6 @@ void states_run(struct StateMachineInput smi);
9 9
 State *states_get(void);
10 10
 void states_go_to(State *state);
11 11
 
12
-extern StateText sm_error;
12
+extern State sm_error;
13 13
 
14 14
 #endif // _STATES_H_

+ 2
- 1
include/steppers.h Целия файл

@@ -2,12 +2,13 @@
2 2
 #define _STEPPERS_H_
3 3
 
4 4
 void steppers_init(void);
5
-bool steppers_run(void);
5
+void steppers_run(void);
6 6
 
7 7
 bool steppers_homed(void);
8 8
 char steppers_homing_axis(void);
9 9
 void steppers_start_homing(void);
10 10
 
11
+bool stepper_reached_target(int axis);
11 12
 float steppers_current_pos(int axis);
12 13
 
13 14
 // target pos

+ 15
- 2
src/common.cpp Целия файл

@@ -3,15 +3,23 @@
3 3
 #include "config.h"
4 4
 #include "config_pins.h"
5 5
 
6
+//#define DISABLE_BEEPING
7
+
6 8
 unsigned long last_led_blink_time = 0;
9
+
10
+#ifndef DISABLE_BEEPING
7 11
 unsigned long beep_stop_time = 0;
12
+#endif // DISABLE_BEEPING
8 13
 
9 14
 void async_beep(int time, int freq) {
15
+#ifndef DISABLE_BEEPING
10 16
     beep_stop_time = millis() + time;
11 17
     tone(BEEPER, freq);
18
+#endif // DISABLE_BEEPING
12 19
 }
13 20
 
14 21
 void blocking_beep(int time, int freq, int repeat = 0) {
22
+#ifndef DISABLE_BEEPING
15 23
     for (int i = 0; i <= repeat; i++) {
16 24
         tone(BEEPER, freq);
17 25
         delay(time);
@@ -21,18 +29,23 @@ void blocking_beep(int time, int freq, int repeat = 0) {
21 29
             delay(time);
22 30
         }
23 31
     }
32
+#endif // DISABLE_BEEPING
24 33
 }
25 34
 
26
-void common_run(unsigned long t) {
35
+void common_run(void) {
36
+    unsigned long t = millis();
37
+
38
+#ifndef DISABLE_BEEPING
27 39
     // stop async beep
28 40
     if ((beep_stop_time > 0)  && (t > beep_stop_time)) {
29 41
         noTone(BEEPER);
30 42
         beep_stop_time = 0;
31 43
     }
44
+#endif // DISABLE_BEEPING
32 45
 
33 46
     // blink heartbeat LED
34 47
     if ((t - last_led_blink_time) >= LED_BLINK_INTERVAL) {
35
-        last_led_blink_time = millis();
48
+        last_led_blink_time = t;
36 49
         digitalWrite(LED_PIN, !digitalRead(LED_PIN));
37 50
     }
38 51
 }

+ 33
- 17
src/data.cpp Целия файл

@@ -37,20 +37,30 @@ static unsigned int max_presets(void) {
37 37
 }
38 38
 
39 39
 static uint32_t data_checksum(struct data_config *data) {
40
+    uint32_t temp_checksum = data->checksum;
41
+    data->checksum = 0;
42
+
43
+    struct data_config_preset *temp_presets = data->presets;
44
+    data->presets = NULL;
45
+
40 46
     uint32_t c = 0;
41 47
 
48
+
42 49
     uint8_t *t = (uint8_t *)data;
43 50
     for (unsigned int i = 0; i < sizeof(struct data_config); i++) {
44 51
         c ^= t[i];
45 52
     }
46 53
 
47 54
     for (unsigned int i = 0; i < data->preset_count; i++) {
48
-        t = (uint8_t *)(&data->presets[i]);
55
+        t = (uint8_t *)(temp_presets + i);
49 56
         for (unsigned int j = 0; j < sizeof(struct data_config_preset); j++) {
50 57
             c ^= t[j];
51 58
         }
52 59
     }
53 60
 
61
+    data->checksum = temp_checksum;
62
+    data->presets = temp_presets;
63
+
54 64
     return c;
55 65
 }
56 66
 
@@ -94,7 +104,6 @@ bool data_eeprom_read(void) {
94 104
 
95 105
     // verify checksum
96 106
     uint32_t read_checksum = config.checksum;
97
-    config.checksum = 0;
98 107
     uint32_t checksum = data_checksum(&config);
99 108
     if (read_checksum == checksum) {
100 109
         // verify version
@@ -112,7 +121,7 @@ bool data_eeprom_read(void) {
112 121
         }
113 122
     } else {
114 123
         Serial.print(F("checksum read="));
115
-        Serial.print(config.checksum);
124
+        Serial.print(read_checksum);
116 125
         Serial.print(F(" calc="));
117 126
         Serial.println(checksum);
118 127
         last_error = "Checksum";
@@ -121,7 +130,6 @@ bool data_eeprom_read(void) {
121 130
 }
122 131
 
123 132
 void data_eeprom_write(void) {
124
-    d.checksum = 0;
125 133
     d.checksum = data_checksum(&d);
126 134
 
127 135
     // write meta-data and settings
@@ -142,6 +150,27 @@ void data_eeprom_write(void) {
142 150
 }
143 151
 
144 152
 void data_init(void) {
153
+    d.presets = NULL;
154
+    data_clear();
155
+
156
+    Serial.print(F("EEPROM max presets: "));
157
+    Serial.println(max_presets());
158
+
159
+    Serial.print(F("EEPROM read... "));
160
+    if (!data_eeprom_read()) {
161
+        Serial.print(last_error);
162
+        Serial.println(F(" Error"));
163
+    } else {
164
+        Serial.println(F("Ok"));
165
+    }
166
+}
167
+
168
+void data_clear(void) {
169
+    if (d.presets != NULL) {
170
+        free(d.presets);
171
+        d.presets = NULL;
172
+    }
173
+
145 174
     d.data_schema_version = DATA_SCHEMA_VERSION;
146 175
     d.preset_count = 0;
147 176
     d.checksum = 0;
@@ -155,19 +184,6 @@ void data_init(void) {
155 184
     d.options.accel_y = XY_MAX_ACCEL;
156 185
     d.options.accel_z = Z_MAX_ACCEL;
157 186
     d.options.accel_e = E_MAX_ACCEL;
158
-
159
-    d.presets = NULL;
160
-
161
-    Serial.print(F("EEPROM max presets: "));
162
-    Serial.println(max_presets());
163
-
164
-    Serial.print(F("EEPROM read... "));
165
-    if (!data_eeprom_read()) {
166
-        Serial.print(last_error);
167
-        Serial.println(F(" Error"));
168
-    } else {
169
-        Serial.println(F("Ok"));
170
-    }
171 187
 }
172 188
 
173 189
 struct data_config_options *data_options(void) {

+ 32
- 28
src/encoder.cpp Целия файл

@@ -42,32 +42,9 @@ void encoder_run(void) {
42 42
 #ifdef KILL_PIN
43 43
     kill_state = kill.poll();
44 44
 #endif // KILL_PIN
45
-
46
-    encoder.tick();
47
-}
48
-
49
-int encoder_change(void) {
50
-    int new_pos = encoder.getPosition();
51
-    int diff = new_pos - pos;
52
-    pos = new_pos;
53
-
54
-#ifdef DEBUG_ENCODER
55
-    if (diff != 0) {
56
-        Serial.print(F("encoder_change: "));
57
-        Serial.print(diff);
58
-        Serial.print(F(" ticks: "));
59
-        Serial.println(new_pos);
60
-    }
61
-#endif // DEBUG_ENCODER
62
-
63
-    return diff;
64
-}
65
-
66
-int encoder_rpm(void) {
67
-    return encoder.getRPM();
68 45
 }
69 46
 
70
-int encoder_click(void) {
47
+bool encoder_click(void) {
71 48
     int r = click_state;
72 49
 
73 50
     // only return 1 once for each click
@@ -80,10 +57,10 @@ int encoder_click(void) {
80 57
 #endif // DEBUG_ENCODER
81 58
     }
82 59
 
83
-    return r;
60
+    return r ? true : false;
84 61
 }
85 62
 
86
-int kill_switch(void) {
63
+bool kill_switch(void) {
87 64
 #ifdef KILL_PIN
88 65
 #ifdef DEBUG_ENCODER
89 66
     if (kill_state == 1) {
@@ -91,8 +68,35 @@ int kill_switch(void) {
91 68
     }
92 69
 #endif // DEBUG_ENCODER
93 70
 
94
-    return kill_state;
71
+    return kill_state ? true : false;
95 72
 #else
96
-    return 0;
73
+    return false;
97 74
 #endif // KILL_PIN
98 75
 }
76
+
77
+// --------------------------------------
78
+
79
+void encoder_run_fast(void) {
80
+    encoder.tick();
81
+}
82
+
83
+int encoder_change(void) {
84
+    int new_pos = encoder.getPosition();
85
+    int diff = new_pos - pos;
86
+    pos = new_pos;
87
+
88
+#ifdef DEBUG_ENCODER
89
+    if (diff != 0) {
90
+        Serial.print(F("encoder_change: "));
91
+        Serial.print(diff);
92
+        Serial.print(F(" ticks: "));
93
+        Serial.println(new_pos);
94
+    }
95
+#endif // DEBUG_ENCODER
96
+
97
+    return diff;
98
+}
99
+
100
+int encoder_rpm(void) {
101
+    return encoder.getRPM();
102
+}

+ 74
- 17
src/main.cpp Целия файл

@@ -10,7 +10,8 @@
10 10
 #include "steppers.h"
11 11
 #include "states.h"
12 12
 
13
-static volatile bool still_running = false;
13
+const static float hz = min(max(max(XY_MAX_HZ, Z_MAX_HZ), E_MAX_HZ), MAX_SAMPLE_FREQ);
14
+const static float us = (1000.0 * 1000.0) / hz;
14 15
 
15 16
 void print_data(void) {
16 17
     Serial.println(F("XY:"));
@@ -88,11 +89,29 @@ void print_data(void) {
88 89
     Serial.println(F(" percent/s^2"));
89 90
 
90 91
     Serial.println();
92
+
93
+    // ----------------------------------
94
+
95
+    Serial.print(F("XY max move freq: "));
96
+    Serial.print(XY_MAX_HZ);
97
+    Serial.println(F("hz"));
98
+    Serial.print(F("Z max move freq: "));
99
+    Serial.print(Z_MAX_HZ);
100
+    Serial.println(F("hz"));
101
+    Serial.print(F("E max move freq: "));
102
+    Serial.print(E_MAX_HZ);
103
+    Serial.println(F("hz"));
104
+
105
+    Serial.print(F("Sample Freq: "));
106
+    Serial.print(hz);
107
+    Serial.print(F("Hz = "));
108
+    Serial.print(us);
109
+    Serial.println(F("us"));
91 110
 }
92 111
 
93 112
 void fast_loop(void) {
94
-    still_running = steppers_run();
95
-    encoder_run();
113
+    steppers_run();
114
+    encoder_run_fast();
96 115
 }
97 116
 
98 117
 void setup() {
@@ -102,10 +121,6 @@ void setup() {
102 121
     pinMode(BEEPER, OUTPUT);
103 122
     blocking_beep(100, 1000);
104 123
 
105
-    // turn on fan connected to D8 for electronics
106
-    pinMode(FAN_PIN, OUTPUT);
107
-    digitalWrite(FAN_PIN, HIGH);
108
-
109 124
     Serial.begin(115200);
110 125
     Serial.println(F("Initializing Fuellfix v2"));
111 126
     Serial.print(F("Version: "));
@@ -123,14 +138,14 @@ void setup() {
123 138
     Serial.println(F("Init stepper motors"));
124 139
     steppers_init();
125 140
 
126
-    print_data();
141
+    //print_data();
127 142
 
128 143
     Serial.println(F("ready, showing splash screen"));
129 144
     digitalWrite(LED_PIN, LOW);
130 145
     blocking_beep(100, 2000);
131 146
 
132 147
     // wait some time to show splash screen
133
-    delay(2000);
148
+    while (millis() < 1500) { }
134 149
 
135 150
     Serial.println(F("Init state machine"));
136 151
     states_init();
@@ -138,27 +153,69 @@ void setup() {
138 153
     blocking_beep(100, 2000);
139 154
     Serial.println(F("starting main loop"));
140 155
 
141
-    Timer1.initialize(1000); // 1000us -> 1kHz
156
+    Timer1.initialize(us);
142 157
     Timer1.attachInterrupt(fast_loop);
143 158
 }
144 159
 
145 160
 void loop() {
146
-    common_run(millis());
161
+    common_run();
162
+    encoder_run();
163
+
164
+    bool click = encoder_click();
165
+    bool kill = kill_switch();
147 166
 
148 167
     CLEAR_STORE_INTERRUPTS();
149 168
 
150
-    int click = encoder_click();
151 169
     int change = encoder_change();
152 170
     int rpm = encoder_rpm();
153
-    int kill = kill_switch();
154
-    bool motors_done = !still_running;
171
+
172
+    bool motor_done[AXIS_COUNT];
173
+    bool all_done = true;
174
+    for (int i = 0; i < AXIS_COUNT; i++) {
175
+        motor_done[i] = stepper_reached_target(i);
176
+        if (!motor_done[i]) {
177
+            all_done = false;
178
+        }
179
+    }
155 180
 
156 181
     RESTORE_INTERRUPTS();
157 182
 
158
-    struct StateMachineInput smi(click, change, rpm, kill, motors_done);
183
+    // allow rudimentary control over serial
184
+    // with enter and w/s or arrow up/down for encoder
185
+    // and q/k/space keys for kill
186
+    static int ser_state = 0;
187
+    while (Serial.available()) {
188
+        int c = Serial.read();
189
+        if (ser_state == 0) {
190
+            if (c == '\n') {
191
+                click = 1;
192
+            } else if ((c == 'q') || (c == 'Q') || (c == 'k') || (c == 'K') || (c == ' ')) {
193
+                kill = 1;
194
+            } else if ((c == 'w') || (c == 'W')) {
195
+                change = 1;
196
+            } else if ((c == 's') || (c == 'S')) {
197
+                change = -1;
198
+            } else if (c == '\e') {
199
+                ser_state = 1;
200
+            }
201
+        } else if (ser_state == 1) {
202
+            if (c == '[') {
203
+                ser_state = 2;
204
+            } else {
205
+                ser_state = 0;
206
+            }
207
+        } else if (ser_state == 2) {
208
+            if (c == 'A') {
209
+                change = 1;
210
+            } else if (c == 'B') {
211
+                change = -1;
212
+            }
213
+            ser_state = 0;
214
+        }
215
+    }
216
+
217
+    struct StateMachineInput smi(click, change, rpm, kill, motor_done, all_done);
159 218
     states_run(smi);
160 219
 
161 220
     lcd_loop();
162
-
163
-    delay(10);
164 221
 }

+ 225
- 0
src/sm_menu.cpp Целия файл

@@ -0,0 +1,225 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "config_pins.h"
5
+#include "lcd.h"
6
+#include "states.h"
7
+
8
+template <typename T, size_t N>
9
+void array_print(Array<T, N> *arr) {
10
+    Serial.print(F("Array length: "));
11
+    Serial.print(arr->size());
12
+    Serial.println(F(" contents:"));
13
+    for (int i = 0; i < arr->size(); i++) {
14
+        Serial.print(i);
15
+        Serial.print(F(": "));
16
+        Serial.println(arr->at(i)->getTitle());
17
+    }
18
+}
19
+
20
+template <typename T, size_t N>
21
+void array_insert_at_pos(Array<T, N> *arr, T value, size_t pos) {
22
+    // make additional space
23
+    arr->push_back(value);
24
+
25
+    if ((pos >= arr->max_size()) || (pos >= arr->size())) {
26
+        // we can not shift it to the given position
27
+        return;
28
+    }
29
+
30
+    for (int i = arr->size() - 2; i >= pos; i--) {
31
+        arr->at(i + 1) = arr->at(i);
32
+    }
33
+
34
+    arr->at(pos) = value;
35
+}
36
+
37
+// --------------------------------------
38
+
39
+StateMenu::StateMenu(State *_parent, bool _show_parent) : State(_parent) {
40
+    show_parent = _show_parent;
41
+    menuPos = 0;
42
+    menuOff = 0;
43
+}
44
+
45
+void StateMenu::setChild(State *_child) {
46
+    children.push_back(_child);
47
+}
48
+
49
+void StateMenu::addChild(State *_child, int pos) {
50
+    if (pos < 0) {
51
+        setChild(_child);
52
+    } else {
53
+        array_insert_at_pos(&children, _child, pos);
54
+    }
55
+}
56
+
57
+void StateMenu::enterState(void) {
58
+    display();
59
+}
60
+
61
+void StateMenu::display(void) {
62
+    lcd_clear();
63
+    lcd_set_heading(getTitle());
64
+
65
+    int size = children.size();
66
+    if (show_parent) {
67
+        size++;
68
+    }
69
+
70
+    for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < size); i++) {
71
+        String s;
72
+        if (i == menuPos) {
73
+            s = F("> ");
74
+        } else {
75
+            s = F("  ");
76
+        }
77
+        if (i == children.size()) {
78
+            s += getParent()->getTitle();
79
+        } else {
80
+            s += children.at(i)->getTitle();
81
+        }
82
+        lcd_set_menu_text(i - menuOff, s.c_str());
83
+    }
84
+}
85
+
86
+void StateMenu::inState(struct StateMachineInput smi) {
87
+    int size = children.size();
88
+    if (show_parent) {
89
+        size++;
90
+    }
91
+
92
+    if (smi.encoder != 0) {
93
+        menuPos -= smi.encoder;
94
+
95
+        while (menuPos < 0) {
96
+            menuPos += size;
97
+        }
98
+
99
+        while (menuPos >= size) {
100
+            menuPos -= size;
101
+        }
102
+
103
+        while (menuPos < menuOff) {
104
+            menuOff--;
105
+        }
106
+
107
+        while (menuPos >= (menuOff + lcd_text_lines())) {
108
+            menuOff++;
109
+        }
110
+
111
+        display();
112
+    }
113
+
114
+    if (smi.click) {
115
+        if (menuPos == children.size()) {
116
+            menuPos = 0;
117
+            menuOff = 0;
118
+            states_go_to(getParent());
119
+        } else {
120
+            states_go_to(children.at(menuPos));
121
+        }
122
+    }
123
+}
124
+
125
+// --------------------------------------
126
+
127
+StateDynamicMenu::StateDynamicMenu(State *_parent) : State(_parent) {
128
+    menuPos = 0;
129
+    menuOff = 0;
130
+    prefix = "";
131
+    countFunc = NULL;
132
+    getFunc = NULL;
133
+    callFunc = NULL;
134
+}
135
+
136
+void StateDynamicMenu::dataCount(CountFuncPtr count) {
137
+    countFunc = count;
138
+}
139
+
140
+void StateDynamicMenu::dataGet(GetFuncPtr get) {
141
+    getFunc = get;
142
+}
143
+
144
+void StateDynamicMenu::dataCall(CallFuncPtr call) {
145
+    callFunc = call;
146
+}
147
+
148
+void StateDynamicMenu::display(void) {
149
+    lcd_clear();
150
+    lcd_set_heading(getTitle());
151
+
152
+    for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < count + 1); i++) {
153
+        String s;
154
+        if (i == menuPos) {
155
+            s = F("> ");
156
+        } else {
157
+            s = F("  ");
158
+        }
159
+        if (i == count) {
160
+            s += getParent()->getTitle();
161
+        } else {
162
+            s += contents.at(i);
163
+        }
164
+        lcd_set_menu_text(i - menuOff, s.c_str());
165
+    }
166
+}
167
+
168
+void StateDynamicMenu::setPrefix(String pre) {
169
+    prefix = pre;
170
+}
171
+
172
+void StateDynamicMenu::enterState(void) {
173
+    // cache all entries on entering state
174
+    if (countFunc != NULL) {
175
+        count = countFunc();
176
+    } else {
177
+        count = 0;
178
+    }
179
+    contents.clear();
180
+    for (int i = 0; i < count; i++) {
181
+        if (getFunc != NULL) {
182
+            contents.push_back(prefix + String(getFunc(i)));
183
+        } else {
184
+            contents.push_back(prefix + String(i + 1));
185
+        }
186
+    }
187
+
188
+    display();
189
+}
190
+
191
+void StateDynamicMenu::inState(StateMachineInput smi) {
192
+    if (smi.encoder != 0) {
193
+        menuPos -= smi.encoder;
194
+
195
+        while (menuPos < 0) {
196
+            menuPos += count + 1;
197
+        }
198
+
199
+        while (menuPos >= count + 1) {
200
+            menuPos -= count + 1;
201
+        }
202
+
203
+        while (menuPos < menuOff) {
204
+            menuOff--;
205
+        }
206
+
207
+        while (menuPos >= (menuOff + lcd_text_lines())) {
208
+            menuOff++;
209
+        }
210
+
211
+        display();
212
+    }
213
+
214
+    if (smi.click) {
215
+        if (menuPos == count) {
216
+            menuPos = 0;
217
+            menuOff = 0;
218
+            states_go_to(getParent());
219
+        } else {
220
+            if (callFunc != NULL) {
221
+                callFunc(menuPos);
222
+            }
223
+        }
224
+    }
225
+}

+ 239
- 0
src/sm_value.cpp Целия файл

@@ -0,0 +1,239 @@
1
+#include <Arduino.h>
2
+
3
+#include "config.h"
4
+#include "config_pins.h"
5
+#include "lcd.h"
6
+#include "states.h"
7
+
8
+template <typename T>
9
+StateValue<T>::StateValue(State *_parent, T &_value, T _min, T _max) : State(_parent), value(_value) {
10
+    min = _min;
11
+    max = _max;
12
+    heading = NULL;
13
+    text = NULL;
14
+    onEnterFunc = NULL;
15
+    updateFunc = NULL;
16
+    updateLiveFunc = NULL;
17
+}
18
+
19
+template <typename T>
20
+void StateValue<T>::setMax(T _max) {
21
+    max = _max;
22
+}
23
+
24
+template <typename T>
25
+void StateValue<T>::onUpdate(UpdateFuncPtr func) {
26
+    updateFunc = func;
27
+}
28
+
29
+template <typename T>
30
+void StateValue<T>::onLiveUpdate(UpdateFuncPtr func) {
31
+    updateLiveFunc = func;
32
+}
33
+
34
+template <typename T>
35
+void StateValue<T>::display(void) {
36
+    lcd_clear();
37
+    if (heading == NULL) {
38
+        lcd_set_heading(getTitle());
39
+    } else {
40
+        lcd_set_heading(heading);
41
+    }
42
+
43
+    String s = String(min) + F(" .. ") + String(value) + F(" .. ") + String(max);
44
+
45
+    if (text != NULL) {
46
+        s = text + String(F("\n")) + s;
47
+    }
48
+
49
+    lcd_set_text(s.c_str());
50
+}
51
+
52
+
53
+template <typename T>
54
+void StateValue<T>::enterState(void) {
55
+    if (onEnterFunc != NULL) {
56
+        onEnterFunc();
57
+    }
58
+    display();
59
+}
60
+
61
+template <typename T>
62
+void StateValue<T>::inState(StateMachineInput smi) {
63
+    if (smi.encoder != 0) {
64
+        float vf = smi.encoder;
65
+        vf *= 1.0 + ((float)smi.rpm / ENCODER_RPM_VALUE_FACTOR);
66
+        int v = vf;
67
+        value -= v;
68
+        if (value < min) {
69
+            value = min;
70
+        }
71
+        if (value > max) {
72
+            value = max;
73
+        }
74
+        if (updateLiveFunc != NULL) {
75
+            updateLiveFunc(value);
76
+        }
77
+        display();
78
+    }
79
+    if (smi.click) {
80
+        if (updateFunc != NULL) {
81
+            updateFunc(value);
82
+        }
83
+        if (getChild() != NULL) {
84
+            states_go_to(getChild());
85
+        } else if (getParent() != NULL) {
86
+            states_go_to(getParent());
87
+        }
88
+    }
89
+}
90
+
91
+template class StateValue<int>;
92
+template class StateValue<float>;
93
+
94
+// --------------------------------------
95
+
96
+template <typename T, size_t N>
97
+StateValues<T, N>::StateValues(State *_parent) : State(_parent) {
98
+    heading = NULL;
99
+    onEnterFunc = NULL;
100
+    updateFunc = NULL;
101
+    updateLiveFunc = NULL;
102
+    pos = 0;
103
+    editing = false;
104
+}
105
+
106
+template <typename T, size_t N>
107
+void StateValues<T, N>::setData(size_t index, const char *name, T *value, T min, T max) {
108
+    if (index >= N) {
109
+        return;
110
+    }
111
+    values[index] = value;
112
+    mins[index] = min;
113
+    maxs[index] = max;
114
+    texts[index] = name;
115
+}
116
+
117
+template <typename T, size_t N>
118
+void StateValues<T, N>::onUpdate(UpdateFuncPtr func) {
119
+    updateFunc = func;
120
+}
121
+
122
+template <typename T, size_t N>
123
+void StateValues<T, N>::onLiveUpdate(UpdateFuncPtr func) {
124
+    updateLiveFunc = func;
125
+}
126
+
127
+template <typename T, size_t N>
128
+void StateValues<T, N>::display(void) {
129
+    lcd_clear();
130
+
131
+    if (heading == NULL) {
132
+        lcd_set_heading(getTitle());
133
+    } else {
134
+        lcd_set_heading(heading);
135
+    }
136
+
137
+    for (size_t i = 0; i < (N + 1); i++) {
138
+        String s;
139
+
140
+        if (i == pos) {
141
+            if (editing) {
142
+                s = F("# ");
143
+            } else {
144
+                s = F("> ");
145
+            }
146
+        } else {
147
+            s = F("  ");
148
+        }
149
+
150
+        if (i < N) {
151
+            s += texts[i] + String(*(values[i])) + F(" (") + String(mins[i]) + F("/") + String(maxs[i]) + F(")");
152
+        } else {
153
+            if (getChild() != NULL) {
154
+                s += F("Continue");
155
+            } else {
156
+                s += F("Done");
157
+            }
158
+        }
159
+
160
+        lcd_set_menu_text(i, s.c_str());
161
+    }
162
+}
163
+
164
+template <typename T, size_t N>
165
+void StateValues<T, N>::enterState(void) {
166
+    pos = 0;
167
+    if (onEnterFunc != NULL) {
168
+        onEnterFunc();
169
+    }
170
+    display();
171
+}
172
+
173
+template <typename T, size_t N>
174
+void StateValues<T, N>::inState(StateMachineInput smi) {
175
+    if (editing) {
176
+        if (smi.encoder != 0) {
177
+            float vf = smi.encoder;
178
+            vf *= 1.0 + ((float)smi.rpm / ENCODER_RPM_VALUE_FACTOR);
179
+            int v = vf;
180
+            *(values[pos]) -= v;
181
+
182
+            if (*(values[pos]) < mins[pos]) {
183
+                *(values[pos]) = mins[pos];
184
+            }
185
+
186
+            if (*(values[pos]) > maxs[pos]) {
187
+                *(values[pos]) = maxs[pos];
188
+            }
189
+
190
+            if (updateLiveFunc != NULL) {
191
+                updateLiveFunc(pos, *(values[pos]));
192
+            }
193
+
194
+            display();
195
+        }
196
+        if (smi.click) {
197
+            editing = false;
198
+            display();
199
+        }
200
+    } else {
201
+        if (smi.encoder != 0) {
202
+            int tmp = pos;
203
+            tmp -= smi.encoder;
204
+
205
+            while (tmp < 0) {
206
+                tmp += N + 1;
207
+            }
208
+
209
+            while (tmp >= (N + 1)) {
210
+                tmp -= N + 1;
211
+            }
212
+
213
+            pos = tmp;
214
+
215
+            display();
216
+        }
217
+        if (smi.click) {
218
+            if (pos < N) {
219
+                editing = true;
220
+                display();
221
+            } else {
222
+                if (updateFunc != NULL) {
223
+                    for (size_t i = 0; i < N; i++) {
224
+                        updateFunc(i, *(values[i]));
225
+                    }
226
+                }
227
+
228
+                if (getChild() != NULL) {
229
+                    states_go_to(getChild());
230
+                } else if (getParent() != NULL) {
231
+                    states_go_to(getParent());
232
+                }
233
+            }
234
+        }
235
+    }
236
+}
237
+
238
+template class StateValues<uint8_t, 2>;
239
+template class StateValues<float, 2>;

+ 8
- 498
src/statemachine.cpp Целия файл

@@ -5,18 +5,14 @@
5 5
 #include "lcd.h"
6 6
 #include "states.h"
7 7
 
8
-State::State(State *_parent) : parent(_parent), child(NULL), title("no title") {
8
+State::State(State *_parent)
9
+        : parent(_parent), child(NULL), title(""), heading(""), text("") {
9 10
     if (_parent != NULL) {
10 11
         _parent->setChild(this);
11 12
     }
12
-}
13
-
14
-// --------------------------------------
15 13
 
16
-StateText::StateText(State *_parent) : State(_parent) {
17
-    heading = "no heading";
18
-    text = "text missing";
19 14
     onEnterFunc = []() { };
15
+
20 16
     whenInFunc = [](StateMachineInput smi) {
21 17
         State *s = states_get();
22 18
         if (smi.click && (s != NULL)) {
@@ -29,35 +25,21 @@ StateText::StateText(State *_parent) : State(_parent) {
29 25
     };
30 26
 }
31 27
 
32
-void StateText::setHeading(const char *_heading) {
33
-    heading = _heading;
34
-}
35
-
36
-void StateText::setText(const char *_text) {
37
-    text = _text;
38
-}
39
-
40
-void StateText::onEnter(EnterFuncPtr func) {
41
-    onEnterFunc = func;
42
-}
43
-
44
-void StateText::whenIn(InFuncPtr func) {
45
-    whenInFunc = func;
46
-}
47
-
48
-void StateText::updateText(void) {
28
+void State::updateText(void) {
49 29
     lcd_clear();
30
+
50 31
     if (heading != NULL) {
51 32
         lcd_set_heading(heading);
52 33
     } else if (getTitle() != NULL) {
53 34
         lcd_set_heading(getTitle());
54 35
     }
36
+
55 37
     if (text != NULL) {
56 38
         lcd_set_text(text);
57 39
     }
58 40
 }
59 41
 
60
-void StateText::enterState(void) {
42
+void State::enterState(void) {
61 43
     if (onEnterFunc != NULL) {
62 44
         onEnterFunc();
63 45
     }
@@ -65,480 +47,8 @@ void StateText::enterState(void) {
65 47
     updateText();
66 48
 }
67 49
 
68
-void StateText::inState(struct StateMachineInput smi) {
50
+void State::inState(struct StateMachineInput smi) {
69 51
     if (whenInFunc != NULL) {
70 52
         whenInFunc(smi);
71 53
     }
72 54
 }
73
-
74
-// --------------------------------------
75
-
76
-StateMenu::StateMenu(State *_parent, bool _show_parent) : State(_parent) {
77
-    show_parent = _show_parent;
78
-    menuPos = 0;
79
-    menuOff = 0;
80
-}
81
-
82
-void StateMenu::setChild(State *_child) {
83
-    children.push_back(_child);
84
-}
85
-
86
-void StateMenu::addChild(State *_child, int pos) {
87
-    if (pos < 0) {
88
-        setChild(_child);
89
-    } else {
90
-        array_insert_at_pos(&children, _child, pos);
91
-    }
92
-}
93
-
94
-void StateMenu::enterState(void) {
95
-    display();
96
-}
97
-
98
-void StateMenu::display(void) {
99
-    lcd_clear();
100
-    lcd_set_heading(getTitle());
101
-
102
-    int size = children.size();
103
-    if (show_parent) {
104
-        size++;
105
-    }
106
-
107
-    for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < size); i++) {
108
-        String s;
109
-        if (i == menuPos) {
110
-            s = F("> ");
111
-        } else {
112
-            s = F("  ");
113
-        }
114
-        if (i == children.size()) {
115
-            s += getParent()->getTitle();
116
-        } else {
117
-            s += children.at(i)->getTitle();
118
-        }
119
-        lcd_set_menu_text(i - menuOff, s.c_str());
120
-    }
121
-}
122
-
123
-void StateMenu::inState(struct StateMachineInput smi) {
124
-    int size = children.size();
125
-    if (show_parent) {
126
-        size++;
127
-    }
128
-
129
-    if (smi.encoder != 0) {
130
-        menuPos -= smi.encoder;
131
-
132
-        while (menuPos < 0) {
133
-            menuPos += size;
134
-        }
135
-
136
-        while (menuPos >= size) {
137
-            menuPos -= size;
138
-        }
139
-
140
-        while (menuPos < menuOff) {
141
-            menuOff--;
142
-        }
143
-
144
-        while (menuPos >= (menuOff + lcd_text_lines())) {
145
-            menuOff++;
146
-        }
147
-
148
-        display();
149
-    }
150
-
151
-    if (smi.click) {
152
-        if (menuPos == children.size()) {
153
-            menuPos = 0;
154
-            menuOff = 0;
155
-            states_go_to(getParent());
156
-        } else {
157
-            states_go_to(children.at(menuPos));
158
-        }
159
-    }
160
-}
161
-
162
-// --------------------------------------
163
-
164
-StateDynamicMenu::StateDynamicMenu(State *_parent) : State(_parent) {
165
-    menuPos = 0;
166
-    menuOff = 0;
167
-    prefix = "";
168
-    countFunc = NULL;
169
-    getFunc = NULL;
170
-    callFunc = NULL;
171
-}
172
-
173
-void StateDynamicMenu::dataCount(CountFuncPtr count) {
174
-    countFunc = count;
175
-}
176
-
177
-void StateDynamicMenu::dataGet(GetFuncPtr get) {
178
-    getFunc = get;
179
-}
180
-
181
-void StateDynamicMenu::dataCall(CallFuncPtr call) {
182
-    callFunc = call;
183
-}
184
-
185
-void StateDynamicMenu::display(void) {
186
-    lcd_clear();
187
-    lcd_set_heading(getTitle());
188
-
189
-    for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < count + 1); i++) {
190
-        String s;
191
-        if (i == menuPos) {
192
-            s = F("> ");
193
-        } else {
194
-            s = F("  ");
195
-        }
196
-        if (i == count) {
197
-            s += getParent()->getTitle();
198
-        } else {
199
-            s += contents.at(i);
200
-        }
201
-        lcd_set_menu_text(i - menuOff, s.c_str());
202
-    }
203
-}
204
-
205
-void StateDynamicMenu::setPrefix(String pre) {
206
-    prefix = pre;
207
-}
208
-
209
-void StateDynamicMenu::enterState(void) {
210
-    // cache all entries on entering state
211
-    if (countFunc != NULL) {
212
-        count = countFunc();
213
-    } else {
214
-        count = 0;
215
-    }
216
-    contents.clear();
217
-    for (int i = 0; i < count; i++) {
218
-        if (getFunc != NULL) {
219
-            contents.push_back(prefix + String(getFunc(i)));
220
-        } else {
221
-            contents.push_back(prefix + String(i + 1));
222
-        }
223
-    }
224
-
225
-    display();
226
-}
227
-
228
-void StateDynamicMenu::inState(StateMachineInput smi) {
229
-    if (smi.encoder != 0) {
230
-        menuPos -= smi.encoder;
231
-
232
-        while (menuPos < 0) {
233
-            menuPos += count + 1;
234
-        }
235
-
236
-        while (menuPos >= count + 1) {
237
-            menuPos -= count + 1;
238
-        }
239
-
240
-        while (menuPos < menuOff) {
241
-            menuOff--;
242
-        }
243
-
244
-        while (menuPos >= (menuOff + lcd_text_lines())) {
245
-            menuOff++;
246
-        }
247
-
248
-        display();
249
-    }
250
-
251
-    if (smi.click) {
252
-        if (menuPos == count) {
253
-            menuPos = 0;
254
-            menuOff = 0;
255
-            states_go_to(getParent());
256
-        } else {
257
-            if (callFunc != NULL) {
258
-                callFunc(menuPos);
259
-            }
260
-        }
261
-    }
262
-}
263
-
264
-// --------------------------------------
265
-
266
-template <typename T>
267
-StateValue<T>::StateValue(State *_parent, T &_value, T _min, T _max) : State(_parent), value(_value) {
268
-    min = _min;
269
-    max = _max;
270
-    heading = NULL;
271
-    text = NULL;
272
-    onEnterFunc = NULL;
273
-    updateFunc = NULL;
274
-    updateLiveFunc = NULL;
275
-}
276
-
277
-template <typename T>
278
-void StateValue<T>::setHeading(const char *_heading) {
279
-    heading = _heading;
280
-}
281
-
282
-template <typename T>
283
-void StateValue<T>::setText(const char *_text) {
284
-    text = _text;
285
-}
286
-
287
-template <typename T>
288
-void StateValue<T>::onEnter(EnterFuncPtr func) {
289
-    onEnterFunc = func;
290
-}
291
-
292
-template <typename T>
293
-void StateValue<T>::onUpdate(UpdateFuncPtr func) {
294
-    updateFunc = func;
295
-}
296
-
297
-template <typename T>
298
-void StateValue<T>::onLiveUpdate(UpdateFuncPtr func) {
299
-    updateLiveFunc = func;
300
-}
301
-
302
-template <typename T>
303
-void StateValue<T>::display(void) {
304
-    lcd_clear();
305
-    if (heading == NULL) {
306
-        lcd_set_heading(getTitle());
307
-    } else {
308
-        lcd_set_heading(heading);
309
-    }
310
-
311
-    String s = String(min) + F(" .. ") + String(value) + F(" .. ") + String(max);
312
-
313
-    if (text != NULL) {
314
-        s = text + String(F("\n")) + s;
315
-    }
316
-
317
-    lcd_set_text(s.c_str());
318
-}
319
-
320
-
321
-template <typename T>
322
-void StateValue<T>::enterState(void) {
323
-    if (onEnterFunc != NULL) {
324
-        onEnterFunc();
325
-    }
326
-    display();
327
-}
328
-
329
-template <typename T>
330
-void StateValue<T>::inState(StateMachineInput smi) {
331
-    if (smi.encoder != 0) {
332
-        float vf = smi.encoder;
333
-        vf *= 1.0 + ((float)smi.rpm / ENCODER_RPM_VALUE_FACTOR);
334
-        int v = vf;
335
-        value -= v;
336
-        if (value < min) {
337
-            value = min;
338
-        }
339
-        if (value > max) {
340
-            value = max;
341
-        }
342
-        if (updateLiveFunc != NULL) {
343
-            updateLiveFunc(value);
344
-        }
345
-        display();
346
-    }
347
-    if (smi.click) {
348
-        if (updateFunc != NULL) {
349
-            updateFunc(value);
350
-        }
351
-        states_go_to(getParent());
352
-    }
353
-}
354
-
355
-template class StateValue<int>;
356
-template class StateValue<float>;
357
-
358
-// --------------------------------------
359
-
360
-template <typename T, size_t N>
361
-StateValues<T, N>::StateValues(State *_parent) : State(_parent) {
362
-    heading = NULL;
363
-    onEnterFunc = NULL;
364
-    updateFunc = NULL;
365
-    updateLiveFunc = NULL;
366
-    pos = 0;
367
-    editing = false;
368
-}
369
-
370
-template <typename T, size_t N>
371
-void StateValues<T, N>::setData(size_t index, const char *name, T *value, T min, T max) {
372
-    if (index >= N) {
373
-        return;
374
-    }
375
-    values[index] = value;
376
-    mins[index] = min;
377
-    maxs[index] = max;
378
-    texts[index] = name;
379
-}
380
-
381
-template <typename T, size_t N>
382
-void StateValues<T, N>::setHeading(const char *_heading) {
383
-    heading = _heading;
384
-}
385
-
386
-template <typename T, size_t N>
387
-void StateValues<T, N>::onEnter(EnterFuncPtr func) {
388
-    onEnterFunc = func;
389
-}
390
-
391
-template <typename T, size_t N>
392
-void StateValues<T, N>::onUpdate(UpdateFuncPtr func) {
393
-    updateFunc = func;
394
-}
395
-
396
-template <typename T, size_t N>
397
-void StateValues<T, N>::onLiveUpdate(UpdateFuncPtr func) {
398
-    updateLiveFunc = func;
399
-}
400
-
401
-template <typename T, size_t N>
402
-void StateValues<T, N>::display(void) {
403
-    lcd_clear();
404
-
405
-    if (heading == NULL) {
406
-        lcd_set_heading(getTitle());
407
-    } else {
408
-        lcd_set_heading(heading);
409
-    }
410
-
411
-    for (size_t i = 0; i < (N + 1); i++) {
412
-        String s;
413
-
414
-        if (i == pos) {
415
-            if (editing) {
416
-                s = F("# ");
417
-            } else {
418
-                s = F("> ");
419
-            }
420
-        } else {
421
-            s = F("  ");
422
-        }
423
-
424
-        if (i < N) {
425
-            s += texts[i] + String(*(values[i])) + F(" (") + String(mins[i]) + F("/") + String(maxs[i]) + F(")");
426
-        } else {
427
-            if (getChild() != NULL) {
428
-                s += F("Continue");
429
-            } else {
430
-                s += F("Done");
431
-            }
432
-        }
433
-
434
-        lcd_set_menu_text(i, s.c_str());
435
-    }
436
-}
437
-
438
-template <typename T, size_t N>
439
-void StateValues<T, N>::enterState(void) {
440
-    pos = 0;
441
-    if (onEnterFunc != NULL) {
442
-        onEnterFunc();
443
-    }
444
-    display();
445
-}
446
-
447
-template <typename T, size_t N>
448
-void StateValues<T, N>::inState(StateMachineInput smi) {
449
-    if (editing) {
450
-        if (smi.encoder != 0) {
451
-            float vf = smi.encoder;
452
-            vf *= 1.0 + ((float)smi.rpm / ENCODER_RPM_VALUE_FACTOR);
453
-            int v = vf;
454
-            *(values[pos]) -= v;
455
-
456
-            if (*(values[pos]) < mins[pos]) {
457
-                *(values[pos]) = mins[pos];
458
-            }
459
-
460
-            if (*(values[pos]) > maxs[pos]) {
461
-                *(values[pos]) = maxs[pos];
462
-            }
463
-
464
-            if (updateLiveFunc != NULL) {
465
-                updateLiveFunc(pos, *(values[pos]));
466
-            }
467
-
468
-            display();
469
-        }
470
-        if (smi.click) {
471
-            editing = false;
472
-            display();
473
-        }
474
-    } else {
475
-        if (smi.encoder != 0) {
476
-            int tmp = pos;
477
-            tmp -= smi.encoder;
478
-
479
-            while (tmp < 0) {
480
-                tmp += N + 1;
481
-            }
482
-
483
-            while (tmp >= (N + 1)) {
484
-                tmp -= N + 1;
485
-            }
486
-
487
-            pos = tmp;
488
-
489
-            display();
490
-        }
491
-        if (smi.click) {
492
-            if (pos < N) {
493
-                editing = true;
494
-                display();
495
-            } else {
496
-                if (updateFunc != NULL) {
497
-                    for (size_t i = 0; i < N; i++) {
498
-                        updateFunc(i, *(values[i]));
499
-                    }
500
-                }
501
-
502
-                if (getChild() != NULL) {
503
-                    states_go_to(getChild());
504
-                } else if (getParent() != NULL) {
505
-                    states_go_to(getParent());
506
-                }
507
-            }
508
-        }
509
-    }
510
-}
511
-
512
-template class StateValues<uint8_t, 2>;
513
-template class StateValues<float, 2>;
514
-
515
-// --------------------------------------
516
-
517
-template <typename T, size_t N>
518
-void array_print(Array<T, N> *arr) {
519
-    Serial.print(F("Array length: "));
520
-    Serial.print(arr->size());
521
-    Serial.println(F(" contents:"));
522
-    for (int i = 0; i < arr->size(); i++) {
523
-        Serial.print(i);
524
-        Serial.print(F(": "));
525
-        Serial.println(arr->at(i)->getTitle());
526
-    }
527
-}
528
-
529
-template <typename T, size_t N>
530
-void array_insert_at_pos(Array<T, N> *arr, T value, size_t pos) {
531
-    // make additional space
532
-    arr->push_back(value);
533
-
534
-    if ((pos >= arr->max_size()) || (pos >= arr->size())) {
535
-        // we can not shift it to the given position
536
-        return;
537
-    }
538
-
539
-    for (int i = arr->size() - 2; i >= pos; i--) {
540
-        arr->at(i + 1) = arr->at(i);
541
-    }
542
-
543
-    arr->at(pos) = value;
544
-}

+ 275
- 32
src/states.cpp Целия файл

@@ -15,23 +15,35 @@
15 15
 
16 16
 // --------------------------------------
17 17
 
18
-StateText sm_ask_homing = StateText();
19
-StateText sm_do_homing = StateText(&sm_ask_homing);
18
+int preset_selection = 0, dispense_off = 0,  dispense_count = 0, dispense_index = 0;
19
+float move_pos_x = 0.0, move_pos_y = 0.0, move_pos_z = 0.0, move_pos_e = 0.0;
20
+
21
+State sm_ask_homing = State();
22
+State sm_do_homing = State(&sm_ask_homing);
20 23
 StateMenu sm_menu = StateMenu(&sm_do_homing, false);
21 24
 
22 25
 StateMenu sm_auto = StateMenu(&sm_menu);
23 26
 StateDynamicMenu sm_presets = StateDynamicMenu(&sm_auto);
24
-// TODO dispense
25 27
 
26
-StateText sm_new_preset = StateText(&sm_auto);
27
-StateText sm_wiz_move = StateText(&sm_new_preset);
28
+StateValue<int> sm_disp_off = StateValue<int>(&sm_presets, dispense_off, 1, 1);
29
+StateValue<int> sm_disp_cnt = StateValue<int>(&sm_disp_off, dispense_count, 1, 1);
30
+State sm_disp_go = State(&sm_disp_cnt);
31
+State sm_disp_run_z_travel = State(&sm_disp_go);
32
+State sm_disp_run_xy_travel = State(&sm_disp_run_z_travel);
33
+State sm_disp_run_z_disp = State(&sm_disp_run_xy_travel);
34
+State sm_disp_run = State(&sm_disp_run_z_disp);
35
+State sm_disp_done = State(&sm_disp_run);
36
+
37
+State sm_new_preset = State(&sm_auto);
38
+State sm_wiz_move = State(&sm_new_preset);
28 39
 StateValues<uint8_t, 2> sm_wiz_count = StateValues<uint8_t, 2>(&sm_wiz_move);
29 40
 StateValues<float, 2> sm_wiz_first_pos = StateValues<float, 2>(&sm_wiz_count);
30 41
 StateValues<float, 2> sm_wiz_last_pos = StateValues<float, 2>(&sm_wiz_first_pos);
31 42
 // TODO move z above container
32
-// TODO move z inside container
43
+// TODO move z inside bottom container
44
+// TODO move z inside top container
33 45
 // TODO move to extruder depth
34
-StateText sm_new_preset_done = StateText(&sm_wiz_last_pos);
46
+State sm_new_preset_done = State(&sm_wiz_last_pos);
35 47
 
36 48
 StateDynamicMenu sm_mod_preset = StateDynamicMenu(&sm_auto);
37 49
 // TODO modify
@@ -39,16 +51,18 @@ StateDynamicMenu sm_mod_preset = StateDynamicMenu(&sm_auto);
39 51
 StateDynamicMenu sm_del_preset = StateDynamicMenu(&sm_auto);
40 52
 // TODO delete
41 53
 
42
-float move_pos_x = 0.0, move_pos_y = 0.0, move_pos_z = 0.0, move_pos_e = 0.0;
43 54
 StateMenu sm_move = StateMenu(&sm_menu);
44 55
 StateValue<float> sm_move_x = StateValue<float>(&sm_move, move_pos_x, X_AXIS_MIN, X_AXIS_MAX);
45 56
 StateValue<float> sm_move_y = StateValue<float>(&sm_move, move_pos_y, Y_AXIS_MIN, Y_AXIS_MAX);
46 57
 StateValue<float> sm_move_z = StateValue<float>(&sm_move, move_pos_z, Z_AXIS_MIN, Z_AXIS_MAX);
47 58
 StateValue<float> sm_move_e = StateValue<float>(&sm_move, move_pos_e, E_AXIS_MIN, E_AXIS_MAX);
48 59
 
60
+State sm_disable_steppers = State(&sm_menu);
61
+
49 62
 StateMenu sm_config = StateMenu(&sm_menu);
50
-StateText sm_conf_load = StateText(&sm_config);
51
-StateText sm_conf_save = StateText(&sm_config);
63
+State sm_conf_load = State(&sm_config);
64
+State sm_conf_save = State(&sm_config);
65
+State sm_conf_clear = State(&sm_config);
52 66
 StateValue<float> sm_conf_speed_xy = StateValue<float>(&sm_config, data_options()->speed_x, 1.0, XY_MAX_SPEED);
53 67
 StateValue<float> sm_conf_speed_z = StateValue<float>(&sm_config, data_options()->speed_z, 1.0, Z_MAX_SPEED);
54 68
 StateValue<float> sm_conf_speed_e = StateValue<float>(&sm_config, data_options()->speed_e, 1.0, E_MAX_SPEED);
@@ -56,16 +70,23 @@ StateValue<float> sm_conf_accel_xy = StateValue<float>(&sm_config, data_options(
56 70
 StateValue<float> sm_conf_accel_z = StateValue<float>(&sm_config, data_options()->accel_z, 1.0, Z_MAX_ACCEL);
57 71
 StateValue<float> sm_conf_accel_e = StateValue<float>(&sm_config, data_options()->accel_e, 1.0, E_MAX_ACCEL);
58 72
 
59
-StateText sm_error = StateText(NULL);
73
+State sm_error = State(NULL);
74
+
75
+#if defined(ENABLE_MOVEMENT_TEST_STATE) || defined(ENABLE_INPUT_TEST_STATE)
76
+StateMenu sm_debug = StateMenu(&sm_menu);
77
+#endif
60 78
 
61 79
 #ifdef ENABLE_MOVEMENT_TEST_STATE
62
-StateMenu sm_movement_test = StateMenu(&sm_menu);
63
-StateText sm_move_x_test = StateText(&sm_movement_test);
64
-StateText sm_move_y_test = StateText(&sm_movement_test);
80
+StateMenu sm_movement_test = StateMenu(&sm_debug);
81
+State sm_move_xy_test = State(&sm_movement_test);
82
+State sm_move_x_test = State(&sm_movement_test);
83
+State sm_move_y_test = State(&sm_movement_test);
84
+State sm_move_z_test = State(&sm_movement_test);
85
+State sm_move_e_test = State(&sm_movement_test);
65 86
 #endif // ENABLE_MOVEMENT_TEST_STATE
66 87
 
67 88
 #ifdef ENABLE_INPUT_TEST_STATE
68
-StateText sm_input_test = StateText(&sm_menu);
89
+State sm_input_test = State(&sm_debug);
69 90
 #endif // ENABLE_INPUT_TEST_STATE
70 91
 
71 92
 // --------------------------------------
@@ -75,6 +96,7 @@ String strbuf;
75 96
 struct data_config_preset wizard_preset = { .count_x = 1, .count_y = 1 };
76 97
 float wizard_first_x = 0.0, wizard_first_y = 0.0;
77 98
 float wizard_last_x = 0.0, wizard_last_y = 0.0;
99
+unsigned long last_state_change = 0, last_input = 0;
78 100
 
79 101
 void states_init(void) {
80 102
     // ----------------------------------
@@ -96,7 +118,7 @@ void states_init(void) {
96 118
 
97 119
     sm_do_homing.whenIn([](StateMachineInput smi) {
98 120
 #ifndef DISABLE_HOMING_STATE
99
-        if (smi.motors_done) {
121
+        if (smi.all_motors_done) {
100 122
             if (steppers_homed()) {
101 123
 #endif // DISABLE_HOMING_STATE
102 124
 
@@ -159,16 +181,144 @@ void states_init(void) {
159 181
         steppers_move_e(v);
160 182
     });
161 183
 
184
+    sm_disable_steppers.setTitle("Disable Steppers");
185
+    sm_disable_steppers.onEnter([]() {
186
+        steppers_kill();
187
+        states_go_to(&sm_ask_homing);
188
+    });
189
+
162 190
     // ----------------------------------
163 191
 
164 192
     sm_auto.setTitle("Filling Menu");
165 193
 
166
-    // TODO
194
+    auto preset_name_func = [](int i) {
195
+        strbuf = String(i + 1);
196
+        strbuf += String(F(" ("));
197
+        strbuf += String(data_preset(i)->count_x);
198
+        strbuf += String(F("*"));
199
+        strbuf += String(data_preset(i)->count_y);
200
+        strbuf += String(F(" / "));
201
+        strbuf += String(data_preset(i)->distance_x);
202
+        strbuf += String(F("*"));
203
+        strbuf += String(data_preset(i)->distance_y);
204
+        strbuf += String(F(")"));
205
+        return strbuf.c_str();
206
+    };
207
+
167 208
     sm_presets.setTitle("Use Preset");
168 209
     sm_presets.setPrefix("Preset ");
169 210
     sm_presets.dataCount([]() {
170 211
         return (int)data_preset_count();
171 212
     });
213
+    sm_presets.dataGet(preset_name_func);
214
+    sm_presets.dataCall([](int i) {
215
+        preset_selection = i;
216
+        states_go_to(&sm_disp_off);
217
+    });
218
+
219
+    sm_disp_off.setTitle("Offset");
220
+    sm_disp_off.setText("Where to start dispensing?");
221
+    sm_disp_off.onEnter([]() {
222
+        dispense_off = 1;
223
+        sm_disp_off.setMax(data_preset(preset_selection)->count_x * data_preset(preset_selection)->count_y);
224
+    });
225
+
226
+    sm_disp_cnt.setTitle("Count");
227
+    sm_disp_cnt.setText("How many to fill?");
228
+    sm_disp_cnt.onEnter([]() {
229
+        dispense_count = data_preset(preset_selection)->count_x * data_preset(preset_selection)->count_y - (dispense_off - 1);
230
+        sm_disp_cnt.setMax(dispense_count);
231
+    });
232
+
233
+    sm_disp_go.setTitle("Confirm");
234
+    sm_disp_go.onEnter([]() {
235
+        dispense_off -= 1;
236
+        strbuf = String(F("Filling from ")) + String(dispense_off + 1);
237
+        strbuf += String(F(" to ")) + String(dispense_off + dispense_count);
238
+        strbuf += String(F("!\nIs this ok?"));
239
+        sm_disp_go.setText(strbuf.c_str());
240
+
241
+        dispense_index = dispense_off;
242
+
243
+        // TODO allow yes/no choice?
244
+    });
245
+
246
+    sm_disp_run_z_travel.setTitle("Z Travel");
247
+    sm_disp_run_z_travel.onEnter([]() {
248
+        // TODO move z to travel height
249
+    });
250
+    sm_disp_run_z_travel.whenIn([](StateMachineInput smi) {
251
+        // TODO update status screen
252
+
253
+        if (smi.all_motors_done) {
254
+            states_go_to(&sm_disp_run_xy_travel);
255
+        }
256
+    });
257
+
258
+    sm_disp_run_xy_travel.setTitle("XY Movement");
259
+    sm_disp_run_xy_travel.onEnter([]() {
260
+        int y = dispense_index / data_preset(preset_selection)->count_x;
261
+        int x = dispense_index % data_preset(preset_selection)->count_x;
262
+
263
+        Serial.print(F("xy_travel: index="));
264
+        Serial.print(dispense_index);
265
+        Serial.print(F(" x="));
266
+        Serial.print(x);
267
+        Serial.print(F(" y="));
268
+        Serial.println(y);
269
+
270
+        float x_pos = data_preset(preset_selection)->offset_x + x * data_preset(preset_selection)->distance_x;
271
+        float y_pos = data_preset(preset_selection)->offset_y + y * data_preset(preset_selection)->distance_y;
272
+
273
+        steppers_move_x(x_pos);
274
+        steppers_move_y(y_pos);
275
+    });
276
+    sm_disp_run_xy_travel.whenIn([](StateMachineInput smi) {
277
+        // TODO update status screen
278
+
279
+        if (smi.all_motors_done) {
280
+            states_go_to(&sm_disp_run_z_disp);
281
+        }
282
+    });
283
+
284
+    sm_disp_run_z_disp.setTitle("Z Dispense");
285
+    sm_disp_run_z_disp.onEnter([]() {
286
+        // TODO move z to dispension height
287
+    });
288
+    sm_disp_run_z_disp.whenIn([](StateMachineInput smi) {
289
+        // TODO update status screen
290
+
291
+        if (smi.all_motors_done) {
292
+            states_go_to(&sm_disp_run);
293
+        }
294
+    });
295
+
296
+    sm_disp_run.setTitle("Dispensing");
297
+    sm_disp_run.onEnter([]() {
298
+        // TODO start dispensing with e and moving z up
299
+    });
300
+    sm_disp_run.whenIn([](StateMachineInput smi) {
301
+        // TODO update status screen
302
+
303
+        if (smi.all_motors_done) {
304
+            dispense_index++;
305
+            if (dispense_index >= (dispense_count + dispense_off)) {
306
+                states_go_to(&sm_disp_done);
307
+            } else {
308
+                states_go_to(&sm_disp_run_z_travel);
309
+            }
310
+        }
311
+    });
312
+
313
+    sm_disp_done.setTitle("Finished");
314
+    sm_disp_done.onEnter([]() {
315
+        // TODO show end screen, "stats"
316
+    });
317
+    sm_disp_done.whenIn([](StateMachineInput smi) {
318
+        if (smi.click) {
319
+            states_go_to(&sm_auto);
320
+        }
321
+    });
172 322
 
173 323
     sm_new_preset.setTitle("Add new Preset");
174 324
     sm_new_preset.setHeading("Preset Wizard");
@@ -180,7 +330,7 @@ void states_init(void) {
180 330
     });
181 331
     sm_wiz_move.whenIn([](StateMachineInput smi) {
182 332
 #ifndef DISABLE_HOMING_STATE
183
-        if (smi.motors_done) {
333
+        if (smi.all_motors_done) {
184 334
             if (steppers_homed()) {
185 335
 #endif // DISABLE_HOMING_STATE
186 336
                 states_go_to(&sm_wiz_count);
@@ -272,13 +422,18 @@ void states_init(void) {
272 422
     sm_mod_preset.dataCount([]() {
273 423
         return (int)data_preset_count();
274 424
     });
425
+    sm_mod_preset.dataGet(preset_name_func);
275 426
 
276
-    // TODO
277 427
     sm_del_preset.setTitle("Delete Preset");
278 428
     sm_del_preset.setPrefix("Preset ");
279 429
     sm_del_preset.dataCount([]() {
280 430
         return (int)data_preset_count();
281 431
     });
432
+    sm_del_preset.dataGet(preset_name_func);
433
+    sm_del_preset.dataCall([](int i) {
434
+        data_preset_remove(i);
435
+        states_go_to(&sm_auto);
436
+    });
282 437
 
283 438
     // ----------------------------------
284 439
 
@@ -311,6 +466,24 @@ void states_init(void) {
311 466
         data_eeprom_write();
312 467
     });
313 468
 
469
+    sm_conf_clear.setTitle("Clear EEPROM & RAM");
470
+    sm_conf_clear.setHeading("Clear EEPROM & RAM");
471
+    sm_conf_clear.setText("EEPROM and RAM Configuration cleared!");
472
+    sm_conf_clear.onEnter([]() {
473
+        data_clear();
474
+        data_eeprom_write();
475
+
476
+        // reapply default conf values
477
+        steppers_set_speed_x(data_options()->speed_x);
478
+        steppers_set_speed_y(data_options()->speed_y);
479
+        steppers_set_speed_z(data_options()->speed_z);
480
+        steppers_set_speed_e(data_options()->speed_e);
481
+        steppers_set_accel_x(data_options()->accel_x);
482
+        steppers_set_accel_y(data_options()->accel_y);
483
+        steppers_set_accel_z(data_options()->accel_z);
484
+        steppers_set_accel_e(data_options()->accel_e);
485
+    });
486
+
314 487
     sm_conf_speed_xy.setTitle("XY Speed");
315 488
     sm_conf_speed_xy.onUpdate([](float v) {
316 489
         steppers_set_speed_x(v);
@@ -346,45 +519,97 @@ void states_init(void) {
346 519
     sm_error.setChild(&sm_ask_homing);
347 520
     sm_error.setTitle("Axis Error");
348 521
     sm_error.setHeading("Axis Error");
349
-    sm_error.setText("Endstop has been hit!");
522
+    sm_error.setText("An unknown error occured!");
523
+
524
+#if defined(ENABLE_MOVEMENT_TEST_STATE) || defined(ENABLE_INPUT_TEST_STATE)
525
+    sm_debug.setTitle("Debug Menu");
526
+#endif
350 527
 
351 528
 #ifdef ENABLE_MOVEMENT_TEST_STATE
352 529
     sm_movement_test.setTitle("Movement Test");
353 530
 
531
+    sm_move_xy_test.setTitle("XY Axes");
532
+    sm_move_xy_test.setHeading("XY Move Test");
533
+    sm_move_xy_test.setText("Moving axis through full range with selected speed.");
534
+    sm_move_xy_test.whenIn([](StateMachineInput smi) {
535
+        static bool sx = false, sy = false;
536
+        if (smi.motor_done[X_AXIS]) {
537
+            sx = !sx;
538
+            steppers_move_x(sx ? (X_AXIS_MAX - X_AXIS_EPSILON) : (X_AXIS_MIN + X_AXIS_EPSILON));
539
+        }
540
+        if (smi.motor_done[Y_AXIS]) {
541
+            sy = !sy;
542
+            steppers_move_y(sy ? (Y_AXIS_MAX - Y_AXIS_EPSILON) : (Y_AXIS_MIN + Y_AXIS_EPSILON));
543
+        }
544
+        if (smi.click) {
545
+            states_go_to(&sm_movement_test);
546
+        }
547
+    });
548
+
354 549
     sm_move_x_test.setTitle("X Axis");
355 550
     sm_move_x_test.setHeading("X Move Test");
551
+    sm_move_x_test.setText("Moving axis through full range with selected speed.");
356 552
     sm_move_x_test.whenIn([](StateMachineInput smi) {
357 553
         static bool s = false;
358
-        if (smi.motors_done) {
554
+        if (smi.motor_done[X_AXIS]) {
359 555
             s = !s;
360
-            steppers_move_x(s ? (X_AXIS_MAX - 10.0) : (X_AXIS_MIN + 10.0));
361
-            if (smi.click) {
362
-                states_go_to(&sm_movement_test);
363
-            }
556
+            steppers_move_x(s ? (X_AXIS_MAX - X_AXIS_EPSILON) : (X_AXIS_MIN + X_AXIS_EPSILON));
557
+        }
558
+        if (smi.click) {
559
+            states_go_to(&sm_movement_test);
364 560
         }
365 561
     });
366 562
 
367 563
     sm_move_y_test.setTitle("Y Axis");
368 564
     sm_move_y_test.setHeading("Y Move Test");
565
+    sm_move_y_test.setText("Moving axis through full range with selected speed.");
369 566
     sm_move_y_test.whenIn([](StateMachineInput smi) {
370 567
         static bool s = false;
371
-        if (smi.motors_done) {
568
+        if (smi.motor_done[Y_AXIS]) {
372 569
             s = !s;
373
-            steppers_move_y(s ? (Y_AXIS_MAX - 10.0) : (Y_AXIS_MIN + 10.0));
374
-            if (smi.click) {
375
-                states_go_to(&sm_movement_test);
376
-            }
570
+            steppers_move_y(s ? (Y_AXIS_MAX - Y_AXIS_EPSILON) : (Y_AXIS_MIN + Y_AXIS_EPSILON));
571
+        }
572
+        if (smi.click) {
573
+            states_go_to(&sm_movement_test);
574
+        }
575
+    });
576
+
577
+    sm_move_z_test.setTitle("Z Axis");
578
+    sm_move_z_test.setHeading("Z Move Test");
579
+    sm_move_z_test.setText("Moving axis through full range with selected speed.");
580
+    sm_move_z_test.whenIn([](StateMachineInput smi) {
581
+        static bool s = false;
582
+        if (smi.motor_done[Z_AXIS]) {
583
+            s = !s;
584
+            steppers_move_z(s ? (Z_AXIS_MAX - Z_AXIS_EPSILON) : (Z_AXIS_MIN + Z_AXIS_EPSILON));
585
+        }
586
+        if (smi.click) {
587
+            states_go_to(&sm_movement_test);
588
+        }
589
+    });
590
+
591
+    sm_move_e_test.setTitle("E Axis");
592
+    sm_move_e_test.setHeading("E Move Test");
593
+    sm_move_e_test.setText("Moving axis through full range with selected speed.");
594
+    sm_move_e_test.whenIn([](StateMachineInput smi) {
595
+        static bool s = false;
596
+        if (smi.motor_done[E_AXIS]) {
597
+            s = !s;
598
+            steppers_move_e(s ? (E_AXIS_MAX - E_AXIS_EPSILON) : (E_AXIS_MIN + E_AXIS_EPSILON));
599
+        }
600
+        if (smi.click) {
601
+            states_go_to(&sm_movement_test);
377 602
         }
378 603
     });
379 604
 #endif // ENABLE_MOVEMENT_TEST_STATE
380 605
 
381 606
 #ifdef ENABLE_INPUT_TEST_STATE
382 607
     sm_input_test.setTitle("Input Test");
383
-    sm_input_test.setHeading("Input Test");
608
+    sm_input_test.setHeading("Endstop Test");
384 609
 
385 610
     sm_input_test.whenIn([](StateMachineInput smi) {
386 611
         String s = "Endstops: ";
387
-        for (int i = 0; i < 4; i++) {
612
+        for (int i = 0; i < AXIS_COUNT; i++) {
388 613
             if (steppers_home_switch(i)) {
389 614
                 s += '1';
390 615
             } else {
@@ -408,6 +633,10 @@ void states_init(void) {
408 633
 }
409 634
 
410 635
 void states_run(StateMachineInput smi) {
636
+    if (smi.click || smi.kill || (smi.encoder != 0)) {
637
+        last_input = millis();
638
+    }
639
+
411 640
     if (smi.click) {
412 641
         async_beep(ENCODER_CLICK_BEEP_TIME, ENCODER_CLICK_BEEP_FREQ);
413 642
     }
@@ -420,6 +649,18 @@ void states_run(StateMachineInput smi) {
420 649
         return;
421 650
     }
422 651
 
652
+#if (IDLE_TIMEOUT > 0)
653
+    unsigned long last_time = max(last_input, last_state_change);
654
+    if ((millis() - last_time) > IDLE_TIMEOUT) {
655
+        if (current_state != &sm_ask_homing) {
656
+            Serial.println(F("Idle timeout, disabling motors"));
657
+            steppers_kill();
658
+            states_go_to(&sm_ask_homing);
659
+            return;
660
+        }
661
+    }
662
+#endif // (IDLE_TIMEOUT > 0)
663
+
423 664
     if (current_state != NULL) {
424 665
         current_state->inState(smi);
425 666
     }
@@ -430,6 +671,8 @@ State *states_get(void) {
430 671
 }
431 672
 
432 673
 void states_go_to(State *state) {
674
+    last_state_change = millis();
675
+
433 676
     current_state = state;
434 677
 
435 678
     if (current_state != NULL) {

+ 189
- 128
src/steppers.cpp Целия файл

@@ -14,6 +14,10 @@ static AccelStepper stepper_y(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN, 0, 0,
14 14
 static AccelStepper stepper_z(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN, 0, 0, false);
15 15
 static AccelStepper stepper_e(AccelStepper::DRIVER, E0_STEP_PIN, E0_DIR_PIN, 0, 0, false);
16 16
 
17
+#define HOME_PHASE_START 0
18
+#define HOME_PHASE_BACK 1
19
+#define HOME_PHASE_FINE 2
20
+
17 21
 enum stepper_states {
18 22
     step_disabled,
19 23
     step_not_homed,
@@ -35,6 +39,11 @@ enum stepper_states {
35 39
 static volatile stepper_states state = step_disabled;
36 40
 static volatile unsigned long steppers_home_move_start_time = 0;
37 41
 
42
+static volatile bool x_finished = true;
43
+static volatile bool y_finished = true;
44
+static volatile bool z_finished = true;
45
+static volatile bool e_finished = true;
46
+
38 47
 void steppers_init(void) {
39 48
     pinMode(X_ENDSTOP_PIN, INPUT_PULLUP);
40 49
     pinMode(Y_ENDSTOP_PIN, INPUT_PULLUP);
@@ -54,6 +63,10 @@ void steppers_init(void) {
54 63
     pinMode(E0_STEP_PIN, OUTPUT);
55 64
     pinMode(E0_DIR_PIN, OUTPUT);
56 65
 
66
+    // fan connected to D8 for electronics
67
+    pinMode(FAN_PIN, OUTPUT);
68
+    digitalWrite(FAN_PIN, LOW);
69
+
57 70
     stepper_x.setEnablePin(X_ENABLE_PIN);
58 71
     stepper_x.setPinsInverted(false, false, true);
59 72
     steppers_set_speed_x(data_options()->speed_x);
@@ -76,6 +89,7 @@ void steppers_init(void) {
76 89
 }
77 90
 
78 91
 static void steppers_initiate_home(int axis, int phase) {
92
+#if 0
79 93
     Serial.print(F("steppers_initiate_home("));
80 94
     if (axis == 0) {
81 95
         Serial.print('X');
@@ -91,56 +105,81 @@ static void steppers_initiate_home(int axis, int phase) {
91 105
     Serial.print(F(", "));
92 106
     Serial.print(phase);
93 107
     Serial.println(F(")"));
108
+#endif
94 109
 
95 110
     CLEAR_STORE_INTERRUPTS();
96 111
 
97 112
     steppers_home_move_start_time = millis();
98 113
 
99
-    if (axis == 0) {
114
+    if (axis == X_AXIS) {
100 115
         // x
101
-        if (phase == 0) {
102
-            state = step_homing_x_fast;
103
-            stepper_x.setSpeed(X_HOMING_DIR * X_AXIS_MOVEMENT_DIR * XY_FAST_HOME_SPEED * XY_STEPS_PER_MM);
104
-        } else if (phase == 1) {
116
+        if (phase == HOME_PHASE_START) {
117
+            if (steppers_home_switch(axis)) {
118
+#if (X_MIN_PIN == -1)
119
+                stepper_x.setCurrentPosition(X_AXIS_MAX * XY_STEPS_PER_MM * X_AXIS_MOVEMENT_DIR);
120
+#else
121
+                stepper_x.setCurrentPosition(X_AXIS_MIN * XY_STEPS_PER_MM * X_AXIS_MOVEMENT_DIR);
122
+#endif
123
+
124
+                // TODO order of homing
125
+                steppers_initiate_home(Y_AXIS, HOME_PHASE_START);
126
+            } else {
127
+                state = step_homing_x_fast;
128
+                stepper_x.setSpeed(X_HOMING_DIR * X_AXIS_MOVEMENT_DIR * XY_FAST_HOME_SPEED * XY_STEPS_PER_MM);
129
+            }
130
+        } else if (phase == HOME_PHASE_BACK) {
105 131
             state = step_homing_x_back;
106 132
             stepper_x.setSpeed(-1.0 * X_HOMING_DIR * X_AXIS_MOVEMENT_DIR * XY_FAST_HOME_SPEED * XY_STEPS_PER_MM);
107
-        } else if (phase == 2) {
133
+        } else if (phase == HOME_PHASE_FINE) {
108 134
             state = step_homing_x_slow;
109 135
             stepper_x.setSpeed(X_HOMING_DIR * X_AXIS_MOVEMENT_DIR * XY_SLOW_HOME_SPEED * XY_STEPS_PER_MM);
110 136
         }
111
-    } else if (axis == 1) {
137
+    } else if (axis == Y_AXIS) {
112 138
         // y
113
-        if (phase == 0) {
114
-            state = step_homing_y_fast;
115
-            stepper_y.setSpeed(Y_HOMING_DIR * Y_AXIS_MOVEMENT_DIR * XY_FAST_HOME_SPEED * XY_STEPS_PER_MM);
116
-        } else if (phase == 1) {
139
+        if (phase == HOME_PHASE_START) {
140
+            if (steppers_home_switch(axis)) {
141
+
142
+#if (Y_MIN_PIN == -1)
143
+                stepper_y.setCurrentPosition(Y_AXIS_MAX * XY_STEPS_PER_MM * Y_AXIS_MOVEMENT_DIR);
144
+#else
145
+                stepper_y.setCurrentPosition(Y_AXIS_MIN * XY_STEPS_PER_MM * Y_AXIS_MOVEMENT_DIR);
146
+#endif
147
+
148
+                // TODO order of homing
149
+                //steppers_initiate_home(Z_AXIS, HOME_PHASE_START);
150
+                state = step_homed;
151
+            } else {
152
+                state = step_homing_y_fast;
153
+                stepper_y.setSpeed(Y_HOMING_DIR * Y_AXIS_MOVEMENT_DIR * XY_FAST_HOME_SPEED * XY_STEPS_PER_MM);
154
+            }
155
+        } else if (phase == HOME_PHASE_BACK) {
117 156
             state = step_homing_y_back;
118 157
             stepper_y.setSpeed(-1.0 * Y_HOMING_DIR * Y_AXIS_MOVEMENT_DIR * XY_FAST_HOME_SPEED * XY_STEPS_PER_MM);
119
-        } else if (phase == 2) {
158
+        } else if (phase == HOME_PHASE_FINE) {
120 159
             state = step_homing_y_slow;
121 160
             stepper_y.setSpeed(Y_HOMING_DIR * Y_AXIS_MOVEMENT_DIR * XY_SLOW_HOME_SPEED * XY_STEPS_PER_MM);
122 161
         }
123
-    } else if (axis == 2) {
162
+    } else if (axis == Z_AXIS) {
124 163
         // z
125
-        if (phase == 0) {
164
+        if (phase == HOME_PHASE_START) {
126 165
             state = step_homing_z_fast;
127 166
             stepper_z.setSpeed(Z_HOMING_DIR * Z_AXIS_MOVEMENT_DIR * Z_FAST_HOME_SPEED * Z_STEPS_PER_MM);
128
-        } else if (phase == 1) {
167
+        } else if (phase == HOME_PHASE_BACK) {
129 168
             state = step_homing_z_back;
130 169
             stepper_z.setSpeed(-1.0 * Z_HOMING_DIR * Z_AXIS_MOVEMENT_DIR * Z_FAST_HOME_SPEED * Z_STEPS_PER_MM);
131
-        } else if (phase == 2) {
170
+        } else if (phase == HOME_PHASE_FINE) {
132 171
             state = step_homing_z_slow;
133 172
             stepper_z.setSpeed(Z_HOMING_DIR * Z_AXIS_MOVEMENT_DIR * Z_SLOW_HOME_SPEED * Z_STEPS_PER_MM);
134 173
         }
135
-    } else if (axis == 3) {
174
+    } else if (axis == E_AXIS) {
136 175
         // e
137
-        if (phase == 0) {
176
+        if (phase == HOME_PHASE_START) {
138 177
             state = step_homing_e_fast;
139 178
             stepper_e.setSpeed(E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_FAST_HOME_SPEED * E_STEPS_PER_PERCENT);
140
-        } else if (phase == 1) {
179
+        } else if (phase == HOME_PHASE_BACK) {
141 180
             state = step_homing_e_back;
142 181
             stepper_e.setSpeed(-1.0 * E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_FAST_HOME_SPEED * E_STEPS_PER_PERCENT);
143
-        } else if (phase == 2) {
182
+        } else if (phase == HOME_PHASE_FINE) {
144 183
             state = step_homing_e_slow;
145 184
             stepper_e.setSpeed(E_HOMING_DIR * E_AXIS_MOVEMENT_DIR * E_SLOW_HOME_SPEED * E_STEPS_PER_PERCENT);
146 185
         }
@@ -155,13 +194,13 @@ bool steppers_home_switch(int axis) {
155 194
     bool r = true;
156 195
     CLEAR_STORE_INTERRUPTS();
157 196
 
158
-    if (axis == 0) {
197
+    if (axis == X_AXIS) {
159 198
         r = digitalRead(X_ENDSTOP_PIN) == LOW;
160
-    } else if (axis == 1) {
199
+    } else if (axis == Y_AXIS) {
161 200
         r = digitalRead(Y_ENDSTOP_PIN) == LOW;
162
-    } else if (axis == 2) {
201
+    } else if (axis == Z_AXIS) {
163 202
         r = digitalRead(Z_ENDSTOP_PIN) == LOW;
164
-    } else if (axis == 3) {
203
+    } else if (axis == E_AXIS) {
165 204
         r = digitalRead(E_ENDSTOP_PIN) == LOW;
166 205
     } else {
167 206
         Serial.println(F("home_switch error: invalid axis"));
@@ -171,20 +210,35 @@ bool steppers_home_switch(int axis) {
171 210
     return r;
172 211
 }
173 212
 
213
+bool stepper_reached_target(int axis) {
214
+    if (axis == X_AXIS) {
215
+        return x_finished;
216
+    } else if (axis == Y_AXIS) {
217
+        return y_finished;
218
+    } else if (axis == Z_AXIS) {
219
+        return z_finished;
220
+    } else if (axis == E_AXIS) {
221
+        return e_finished;
222
+    } else {
223
+        Serial.println(F("stepper_reached_target error: invalid axis"));
224
+        return false;
225
+    }
226
+}
227
+
174 228
 float steppers_current_pos(int axis) {
175 229
     float r = 0.0;
176 230
     CLEAR_STORE_INTERRUPTS();
177 231
 
178
-    if (axis == 0) {
232
+    if (axis == X_AXIS) {
179 233
         float v = stepper_x.currentPosition();
180 234
         r = v / XY_STEPS_PER_MM / X_AXIS_MOVEMENT_DIR;
181
-    } else if (axis == 1) {
235
+    } else if (axis == Y_AXIS) {
182 236
         float v = stepper_y.currentPosition();
183 237
         r = v / XY_STEPS_PER_MM / Y_AXIS_MOVEMENT_DIR;
184
-    } else if (axis == 2) {
238
+    } else if (axis == Z_AXIS) {
185 239
         float v = stepper_z.currentPosition();
186 240
         r = v / Z_STEPS_PER_MM / Z_AXIS_MOVEMENT_DIR;
187
-    } else if (axis == 3) {
241
+    } else if (axis == E_AXIS) {
188 242
         float v = stepper_e.currentPosition();
189 243
         r = E_PERCENT_TO_MM(v / E_STEPS_PER_PERCENT / E_AXIS_MOVEMENT_DIR);
190 244
     } else {
@@ -195,22 +249,95 @@ float steppers_current_pos(int axis) {
195 249
     return r;
196 250
 }
197 251
 
198
-bool steppers_run(void) {
199
-    if (state == step_homing_x_fast) {
200
-        if (steppers_home_switch(0)) {
201
-            steppers_initiate_home(0, 1);
252
+// TODO split into separate run funcs for running and homing
253
+// TODO only enable timer1 when either homing or moving
254
+// TODO disable timer1 when no longer homing/moving
255
+// TODO (when timer is disabled, still call in normal loop?)
256
+
257
+void steppers_run(void) {
258
+    if ((state == step_homed) || (state == step_not_homed)) {
259
+        for (int i = 0; i < AXIS_COUNT; i++) {
260
+#if 0
261
+            Serial.print(i);
262
+            Serial.print(": ");
263
+            Serial.println(steppers_current_pos(i));
264
+#endif
265
+
266
+            if (steppers_home_switch(i)) {
267
+                float compare = 0.0, epsilon = 0.0;
268
+                if (i == X_AXIS) {
269
+                    epsilon = X_AXIS_EPSILON;
270
+    #if (X_HOMING_DIR == 1)
271
+                    compare = X_AXIS_MAX;
272
+    #else
273
+                    compare = X_AXIS_MIN;
274
+    #endif
275
+                } else if (i == Y_AXIS) {
276
+                    epsilon = Y_AXIS_EPSILON;
277
+    #if (Y_HOMING_DIR == 1)
278
+                    compare = Y_AXIS_MAX;
279
+    #else
280
+                    compare = Y_AXIS_MIN;
281
+    #endif
282
+                } else if (i == Z_AXIS) {
283
+                    epsilon = Z_AXIS_EPSILON;
284
+    #if (Z_HOMING_DIR == 1)
285
+                    compare = Z_AXIS_MAX;
286
+    #else
287
+                    compare = Z_AXIS_MIN;
288
+    #endif
289
+                } else if (i == E_AXIS) {
290
+                    epsilon = E_AXIS_EPSILON;
291
+    #if (E_HOMING_DIR == 1)
292
+                    compare = E_AXIS_MAX;
293
+    #else
294
+                    compare = E_AXIS_MIN;
295
+    #endif
296
+                }
297
+
298
+                if (fabs(steppers_current_pos(i) - compare) > epsilon) {
299
+#if 0
300
+                    Serial.print(F("Endstop hit at "));
301
+                    Serial.println(steppers_current_pos(i));
302
+#endif
303
+
304
+                    steppers_kill();
305
+
306
+                    if (i == X_AXIS) {
307
+                        sm_error.setText("Enstop hit on X axis");
308
+                    } else if (i == Y_AXIS) {
309
+                        sm_error.setText("Enstop hit on Y axis");
310
+                    } else if (i == Z_AXIS) {
311
+                        sm_error.setText("Enstop hit on Z axis");
312
+                    } else if (i == E_AXIS) {
313
+                        sm_error.setText("Enstop hit on E axis");
314
+                    } else {
315
+                        sm_error.setText("Enstop hit on unknown axis");
316
+                    }
317
+                    states_go_to(&sm_error);
318
+                }
319
+            }
320
+        }
321
+
322
+        x_finished = !stepper_x.run();
323
+        y_finished = !stepper_y.run();
324
+        z_finished = !stepper_z.run();
325
+        e_finished = !stepper_e.run();
326
+    } else if (state == step_homing_x_fast) {
327
+        if (steppers_home_switch(X_AXIS)) {
328
+            steppers_initiate_home(X_AXIS, HOME_PHASE_BACK);
202 329
         } else {
203 330
             stepper_x.runSpeed();
204 331
         }
205 332
     } else if (state == step_homing_x_back) {
206 333
         unsigned long end_time = steppers_home_move_start_time + XY_HOME_BACK_OFF_TIME;
207
-        if ((!steppers_home_switch(0)) && (millis() >= end_time)) {
208
-            steppers_initiate_home(0, 2);
334
+        if ((!steppers_home_switch(X_AXIS)) && (millis() >= end_time)) {
335
+            steppers_initiate_home(X_AXIS, HOME_PHASE_FINE);
209 336
         } else {
210 337
             stepper_x.runSpeed();
211 338
         }
212 339
     } else if (state == step_homing_x_slow) {
213
-        if (steppers_home_switch(0)) {
340
+        if (steppers_home_switch(X_AXIS)) {
214 341
             stepper_x.setSpeed(0);
215 342
 
216 343
 #if (X_MIN_PIN == -1)
@@ -219,25 +346,25 @@ bool steppers_run(void) {
219 346
             stepper_x.setCurrentPosition(X_AXIS_MIN * XY_STEPS_PER_MM * X_AXIS_MOVEMENT_DIR);
220 347
 #endif
221 348
 
222
-            steppers_initiate_home(1, 0);
349
+            steppers_initiate_home(Y_AXIS, HOME_PHASE_START);
223 350
         } else {
224 351
             stepper_x.runSpeed();
225 352
         }
226 353
     } else if (state == step_homing_y_fast) {
227
-        if (steppers_home_switch(1)) {
228
-            steppers_initiate_home(1, 1);
354
+        if (steppers_home_switch(Y_AXIS)) {
355
+            steppers_initiate_home(Y_AXIS, HOME_PHASE_BACK);
229 356
         } else {
230 357
             stepper_y.runSpeed();
231 358
         }
232 359
     } else if (state == step_homing_y_back) {
233 360
         unsigned long end_time = steppers_home_move_start_time + XY_HOME_BACK_OFF_TIME;
234
-        if ((!steppers_home_switch(1)) && (millis() >= end_time)) {
235
-            steppers_initiate_home(1, 2);
361
+        if ((!steppers_home_switch(Y_AXIS)) && (millis() >= end_time)) {
362
+            steppers_initiate_home(Y_AXIS, HOME_PHASE_FINE);
236 363
         } else {
237 364
             stepper_y.runSpeed();
238 365
         }
239 366
     } else if (state == step_homing_y_slow) {
240
-        if (steppers_home_switch(1)) {
367
+        if (steppers_home_switch(Y_AXIS)) {
241 368
             stepper_y.setSpeed(0);
242 369
 
243 370
 #if (Y_MIN_PIN == -1)
@@ -246,28 +373,27 @@ bool steppers_run(void) {
246 373
             stepper_y.setCurrentPosition(Y_AXIS_MIN * XY_STEPS_PER_MM * Y_AXIS_MOVEMENT_DIR);
247 374
 #endif
248 375
 
249
-            //steppers_initiate_home(3, 0);
376
+            //steppers_initiate_home(E_AXIS, HOME_PHASE_START);
250 377
             // TODO
251 378
             state = step_homed;
252
-            return false;
253 379
         } else {
254 380
             stepper_y.runSpeed();
255 381
         }
256 382
     } else if (state == step_homing_z_fast) {
257
-        if (steppers_home_switch(2)) {
258
-            steppers_initiate_home(2, 1);
383
+        if (steppers_home_switch(Z_AXIS)) {
384
+            steppers_initiate_home(Z_AXIS, HOME_PHASE_BACK);
259 385
         } else {
260 386
             stepper_z.runSpeed();
261 387
         }
262 388
     } else if (state == step_homing_z_back) {
263 389
         unsigned long end_time = steppers_home_move_start_time + Z_HOME_BACK_OFF_TIME;
264
-        if ((!steppers_home_switch(2)) && (millis() >= end_time)) {
265
-            steppers_initiate_home(2, 2);
390
+        if ((!steppers_home_switch(Z_AXIS)) && (millis() >= end_time)) {
391
+            steppers_initiate_home(Z_AXIS, HOME_PHASE_FINE);
266 392
         } else {
267 393
             stepper_z.runSpeed();
268 394
         }
269 395
     } else if (state == step_homing_z_slow) {
270
-        if (steppers_home_switch(2)) {
396
+        if (steppers_home_switch(Z_AXIS)) {
271 397
             stepper_z.setSpeed(0);
272 398
 
273 399
 #if (Z_MIN_PIN == -1)
@@ -276,25 +402,25 @@ bool steppers_run(void) {
276 402
             stepper_z.setCurrentPosition(Z_AXIS_MIN * Z_STEPS_PER_MM * Z_AXIS_MOVEMENT_DIR);
277 403
 #endif
278 404
 
279
-            steppers_initiate_home(0, 0);
405
+            steppers_initiate_home(X_AXIS, HOME_PHASE_START);
280 406
         } else {
281 407
             stepper_z.runSpeed();
282 408
         }
283 409
     } else if (state == step_homing_e_fast) {
284
-        if (steppers_home_switch(3)) {
285
-            steppers_initiate_home(3, 1);
410
+        if (steppers_home_switch(E_AXIS)) {
411
+            steppers_initiate_home(E_AXIS, HOME_PHASE_BACK);
286 412
         } else {
287 413
             stepper_e.runSpeed();
288 414
         }
289 415
     } else if (state == step_homing_e_back) {
290 416
         unsigned long end_time = steppers_home_move_start_time + E_HOME_BACK_OFF_TIME;
291
-        if ((!steppers_home_switch(3)) && (millis() >= end_time)) {
292
-            steppers_initiate_home(3, 2);
417
+        if ((!steppers_home_switch(E_AXIS)) && (millis() >= end_time)) {
418
+            steppers_initiate_home(E_AXIS, HOME_PHASE_FINE);
293 419
         } else {
294 420
             stepper_e.runSpeed();
295 421
         }
296 422
     } else if (state == step_homing_e_slow) {
297
-        if (steppers_home_switch(3)) {
423
+        if (steppers_home_switch(E_AXIS)) {
298 424
             stepper_e.setSpeed(0);
299 425
 
300 426
 #if (E_MIN_PIN == -1)
@@ -304,81 +430,10 @@ bool steppers_run(void) {
304 430
 #endif
305 431
 
306 432
             state = step_homed;
307
-            return false;
308 433
         } else {
309 434
             stepper_e.runSpeed();
310 435
         }
311
-    } else if (state != step_disabled) {
312
-        if (state == step_homed) {
313
-            for (int i = 0; i < 4; i++) {
314
-                Serial.print(i);
315
-                Serial.print(": ");
316
-                Serial.println(steppers_current_pos(i));
317
-
318
-                float compare = 0.0, epsilon = 0.0;
319
-                if (i == 0) {
320
-                    epsilon = X_AXIS_EPSILON;
321
-#if (X_MIN_PIN == -1)
322
-                    compare = X_AXIS_MAX;
323
-#else
324
-                    compare = X_AXIS_MIN;
325
-#endif
326
-                } else if (i == 1) {
327
-                    epsilon = Y_AXIS_EPSILON;
328
-#if (Y_MIN_PIN == -1)
329
-                    compare = Y_AXIS_MAX;
330
-#else
331
-                    compare = Y_AXIS_MIN;
332
-#endif
333
-                } else if (i == 2) {
334
-                    epsilon = Z_AXIS_EPSILON;
335
-#if (Z_MIN_PIN == -1)
336
-                    compare = Z_AXIS_MAX;
337
-#else
338
-                    compare = Z_AXIS_MIN;
339
-#endif
340
-                } else if (i == 3) {
341
-                    epsilon = E_AXIS_EPSILON;
342
-#if (E_MIN_PIN == -1)
343
-                    compare = E_AXIS_MAX;
344
-#else
345
-                    compare = E_AXIS_MIN;
346
-#endif
347
-                }
348
-
349
-                if (fabs(steppers_current_pos(i) - compare) > epsilon) {
350
-                    if (steppers_home_switch(i)) {
351
-                        Serial.print(F("Endstop hit at "));
352
-                        Serial.println(steppers_current_pos(i));
353
-
354
-                        steppers_kill();
355
-
356
-                        if (i == 0) {
357
-                            sm_error.setText("Enstop hit on X axis");
358
-                        } else if (i == 1) {
359
-                            sm_error.setText("Enstop hit on Y axis");
360
-                        } else if (i == 2) {
361
-                            sm_error.setText("Enstop hit on Z axis");
362
-                        } else if (i == 3) {
363
-                            sm_error.setText("Enstop hit on E axis");
364
-                        } else {
365
-                            sm_error.setText("Enstop hit on unknown axis");
366
-                        }
367
-                        states_go_to(&sm_error);
368
-                    }
369
-                }
370
-            }
371
-        }
372
-
373
-        boolean x = stepper_x.run();
374
-        boolean y = stepper_y.run();
375
-        boolean z = stepper_z.run();
376
-        boolean e = stepper_e.run();
377
-
378
-        return x || y || z || e;
379 436
     }
380
-
381
-    return true;
382 437
 }
383 438
 
384 439
 bool steppers_homed(void) {
@@ -409,14 +464,16 @@ char steppers_homing_axis(void) {
409 464
 void steppers_start_homing(void) {
410 465
     CLEAR_STORE_INTERRUPTS();
411 466
 
467
+    digitalWrite(FAN_PIN, HIGH);
468
+
412 469
     stepper_x.enableOutputs();
413 470
     stepper_y.enableOutputs();
414 471
     stepper_z.enableOutputs();
415 472
     stepper_e.enableOutputs();
416 473
 
417
-    //steppers_initiate_home(2, 0);
474
+    //steppers_initiate_home(Z_AXIS, HOME_PHASE_START);
418 475
     // TODO
419
-    steppers_initiate_home(0, 0);
476
+    steppers_initiate_home(X_AXIS, HOME_PHASE_START);
420 477
 
421 478
     RESTORE_INTERRUPTS();
422 479
 }
@@ -427,6 +484,8 @@ static int steppers_move_axis(AccelStepper &axis, long pos) {
427 484
     if (state == step_disabled) {
428 485
         Serial.println(F("Enabling stepper drivers"));
429 486
 
487
+        digitalWrite(FAN_PIN, HIGH);
488
+
430 489
         stepper_x.enableOutputs();
431 490
         stepper_y.enableOutputs();
432 491
         stepper_z.enableOutputs();
@@ -567,7 +626,9 @@ void steppers_kill(void) {
567 626
     stepper_z.disableOutputs();
568 627
     stepper_e.disableOutputs();
569 628
 
570
-    state = step_not_homed;
629
+    digitalWrite(FAN_PIN, LOW);
630
+
631
+    state = step_disabled;
571 632
 
572 633
     RESTORE_INTERRUPTS();
573 634
 }

Loading…
Отказ
Запис