-
Notifications
You must be signed in to change notification settings - Fork 2
/
Arduino-DRO.ino
2449 lines (2028 loc) · 68.6 KB
/
Arduino-DRO.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
ArduinoDRO + Tach V6.0
iGaging/AccuRemote Digital Scales Controller V3.3
Created 5 July 2014
Update 15 July 2014
Copyright (C) 2014 Yuriy Krushelnytskiy, http://www.yuriystoys.com
Updated 24 January 2019 by Ryszard Malinowski
http://www.rysium.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Version 2.b - Added support for tachometer on axis T with accurate timing
Version 3.0 - Added option to send rpm raw data (time and count)
Version 5.2 - Correction to retrieving scale sign bit.
Version 5.2 - Corrected scale frequency clock.
Version 5.2 - Added option to pre-scale tach reading compensating for more than one tach pulse per rotation.
Version 5.3 - Added option to average and round tach output values.
Version 5.3 - Added option to select max tach update frequency
Version 5.4 - Replace Yuriy's method of clocking scales with method written by Les Jones
Version 5.5 - Optimizing the scale reading logic using method written by Les Jones
Version 5.6 - Adding 4us delay between scale clock signal change and reading first axis data
Version 5.7 - Added option to smooth DRO reading by implementing weighted average with automatic smoothing factor
Version 5.8 - Correction to calculate average for scale X. Increase weighted average sample size to 32.
Version 5.9 - Reduce flickering on RPM display. Remove long delay in RPM displaying Zero after the rotation stops.
Version 5.10 - Add "smart rounding" on tach display. Fix 1% tach rounding. Support processors running at 8MHz clock.
Version 5.11 - Add "touch probe" support.
Version 5.12 - Fix "touch probe" port definition and comments.
Version 6.0 - Add suport for Quadrature Encoder scales through LS7366R-type shield.
NOTE: This program supports pulse sensor to measure rpm and switch type touch probe . For quadrature encoder scales use LS7366R-based shield.
If at least one quadrature scale is used do not conect other devices to SPI dedicated pins as LS7366R uses SPI for communication
Read your Arduino board documentation for SPI pins as on some boards they are shared with "normal" I/O pins (on Arduino UNO it is 11, 12 and 13).
Configuration parameters:
SCALE_<n>_ENABLED
Defines if DRO functionality on axis <n> should be supported.
If supported DRO scale should be connected to I/O pin defined in constant "<n>DataPin" and
DRO data is sent to serial port with corresponding axis prefix (X, Y, Z or W)
Clock pin is common for all iGaging scales should be connected to I/O pin defined in constant "clockPin"
Possible values:
0 = DRO functionality on axis <n> is not supported
1 = DRO functionality on axis <n> is supported
Default value = 1
SCALE_<n>_TYPE
Defines the type of scale used on axis <n>.
Two types of scales are supported: iGaging/AccuRemote Digital Scales and quadrature encoder scales (common glass or magnetic)
Note: If at least on scale is type 1 do not connect any other devices to SPI pins as it will interfere with communication with LS7366R.
Possible values:
0 = iGaging/AccuRemote Digital Scales with 21bit protocol
1 = Quadrature Encoder scales through LS7366R-type shield (32-bit quadrature counter with serial interface).
Default value = 0
SCALE_CLK_PIN
Defines the I/O pin where clock signal for all iGaging DRO scales is connected. Used only if at least one scale is type 0.
Possible values:
integer number between 2 and 13
Default value = 2
SCALE_<n>_PIN
Defines the I/O pin where DRO data signal for selected scale is connected
Note: For quadrature scale this pin is connected to SPI SS pin in corresponding LS7366R.
Possible values:
integer number between 2 and 13
Default values = 3, 4, 5, 6 (for corresponding axis X, Y, Z and W)
SCALE_<n>_AVERAGE_ENABLED
Defines if DRO reading should be averaged using weighted average calculation with automating smoothing factor.
If average is enabled the reading is much more stable without "jumping" and "flickering" when the scale "can't decide" on the value.
Note: This value is not used when corresponding SCALE_<n>_ENABLED is 0
Possible values:
0 = exact measured from the scale is sent
1 = scale reading averaged using weighted average calculation with automatic smoothing factor
Default value = 1
AXIS_AVERAGE_COUNT
Defines the number of last DRO readings that will be used to calculate weighted average for DRO.
For machines with power feed on any axis change this value to lower number i.e. 8 or 16.
Possible values:
integer number between 4 and 32
Recommended values:
16 for machines with power feed
32 for all manual machines
Default value = 24
TACH_ENABLED
Defines if tach sensor functionality should be supported.
If supported tach sensor should be connected to I/O pin defined in constant INPUT_TACH_PIN and
rpm value is sent to serial port with axis prefix "T"
Possible values:
0 = tach sensor functionality is not supported
1 = tach sensor functionality is supported
Default value = 1
INPUT_TACH_PIN
Defines the I/O pin where tach sensor signal is connected
Possible values:
integer number between 2 and 13
Default value = 7
TACH_PRESCALE
Defines how many tach pulses per one revolution the sensor sends.
For example if tach sensor uses two magnets on the shaft the sensor will generate two pulses per revolution.
This can be used to get better resolution and faster response time for very low rpm
Note: This value is not used when TACH_RAW_DATA_FORMAT is enabled
Possible values:
any integer number greater than 0
Default value = 1
TACH_AVERAGE_COUNT
Defines the number of last tach readings that will be used to calculate average tach rpm.
If you want to send measured rpm instead of average rpm set this value to 1.
Note: This value is not used when TACH_RAW_DATA_FORMAT is enabled.
It is recommended to set this value 2 times or more of TACH_PRESCALE value.
For example: if TACH_PRESCALE = 4, set TACH_AVERAGE_COUNT = 8
Possible values:
1 = exact measured tach reading is sent
any integer number greater than 1 - average tach reading is sent
Default value = 6
TACH_ROUND
Defines how tach reading should be rounded.
If rounding is enabled the reading can be rounded either by 1% of current rpm or to the fixed "round" number with predefined RPM thresholds ("smart rounding").
For example with 1% rounding if measured rpm is between 980rpm and 1020 rpm the display will show numbers rounded to 9 and 10 (i.e. 981, 990, 999, 1000, 1010, 1020 etc.).
With "smart rounding" the measured rpm is rounded to the nearest 1, 2, 5, 10, 20, 50 and 100 depends on measured RPM (change at predefined thresholds).
For example with "smart rounding" all measured rpm is between 500pm and 2000 rpm the display will show numbers rounded to the nearest 5 (i.e. 980, 985, 990, 995, 1000, 1005 etc.).
Note: This value is not used when TACH_RAW_DATA_FORMAT is enabled
Possible values:
0 = exact measured tach reading is sent
1 = tach reading is rounded to the nearest 1% of measured rpm (1% rounding)
2 = tach reading is rounded to the nearest "round" number with fixed thresholds ("smart rounding")
Default value = 2
TACH_RAW_DATA_FORMAT
Defines the format of tach data sent to serial port.
Note: when raw data format is used, then TACH_PRESCALE, TACH_AVERAGE_COUNT and TACH_ROUND are ignored
Possible values:
0 = tach data is sent in single value format: T<rpm>;
1 = tach data is sent in raw (two values) format: T<total_time>/<number_of_pulses>;
Default value = 0
MIN_RPM_DELAY
Defines the delay (in milliseconds) in showing 0 when rotation stops. If rpm is so low and time between tach pulse
changes longer than this value, value zero rpm ("T0;") will be sent to the serial port.
Note: this number will determine the slowest rpm that can be measured. In order to measure smaller rpm I suggest
to use a sensor with more than one "ticks per revolution" (for example hall sensor with two or more magnets).
The number of "ticks per revolution" should be set in tachometer setting in Android app.
Possible values:
any integer number greater than 0
Default value = 1200 (the minimum rpm measured will be 50 rpm)
OUTPUT_TACH_LED_ENABLED
Defines if the tach LED feedback is supported.
If supported the tach feedback LED should be connected to I/O pin defined in constant OUTPUT_TACH_LED_PIN below
Possible values:
0 = tach LED feedback functionality is not supported
1 = tach LED feedback functionality is supported
Default value = 1
OUTPUT_TACH_LED_PIN
Defines the I/O pin where the tach LED feedback is connected.
Tach LED feedback indicates the status of INPUT_TACH_PIN for debugging purposes
Possible values:
integer number between 2 and 13
Default value = 9
PROBE_ENABLED
Defines if touch probe sensor functionality should be supported.
If supported touch probe should be connected to I/O pin defined in constant INPUT_PROBE_PIN.
Possible values:
1 = touch probe functionality is supported
0 = touch probe functionality is not supported
Default value = 1
INPUT_PROBE_PIN
Defines the I/O pin where touch probe signal is connected
Possible values:
integer number between 2 and 13
Default value = 8
PROBE_INVERT
Defines if the touch probe input pin signal needs to be inverted (enter the signal level when touch probe is not touching).
Possible values:
0 = touch probe input pin signal is LOW (logical Zero) when touch probe is in "normal open" status (not touching)
1 = touch probe input pin signal is HIGH (logical One) when touch probe is in "normal open" status (not touching)
Default value = 0
OUTPUT_PROBE_LED_ENABLED
Defines if the touch probe LED feedback is supported.
If supported the touch probe feedback LED should be connected to I/O pin defined in constant INPUT_PROBE_PIN below
Possible values:
1 = touch probe LED feedback functionality is supported
0 = touch probe LED feedback functionality is not supported
Default value = 1
OUTPUT_PROBE_LED_PIN
Defines the I/O pin where the touch probe LED feedback is connected.
Touch probe LED feedback indicates the status of INPUT_PROBE_PIN for debugging purposes
Possible values:
integer number between 2 and 13
Default value = 10
UART_BAUD_RATE
Defines the serial port baud rate. Make sure it matches the Bluetooth module's baud rate.
Recommended value:
1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
Default value = 9600
UPDATE_FREQUENCY
Defines the Frequency in Hz (number of timer per second) the scales are read and the data is sent to the application.
Possible values:
any integer number between 1 and 64
Default value = 24
TACH_UPDATE_FREQUENCY
Defines the max Frequency in Hz (number of timer per second) the tach output is sent to the application.
Note: This value must be a divider of UPDATE_FREQUENCY that would result zero reminder.
For example for UPDATE_FREQUENCY = 24 valid TACH_UPDATE_FREQUENCY are: 1, 2, 3, 4, 6, 8, 12 and 24
Possible values:
any integer number between 1 and UPDATE_FREQUENCY
Default value = 4
*/
/* === Display DRO === */
#include "LedController.hpp"
#include <EEPROM.h>
/*
* pin 12 is connected to the DataIn
* pin 11 is connected to the CLK
* pin 10 is connected to LOAD
*/
#define DISPLAY_COUNT 4
#define DISPLAY_WIDTH 9 // one extra to account for the decimal point
#define MODE_CHAR_ABS 'A'
#define MODE_CHAR_INC ' '
#define MODE_CHAR_SEL '-'
#define DISPLAY_MENU_ADDRESS 3
#define DISPLAY_X_AXIS_ADDRESS 0
#define DISPLAY_Y_AXIS_ADDRESS 1
#define DISPLAY_Z_AXIS_ADDRESS 2
#define DISPLAY_W_AXIS_ADDRESS -1
#define DISPLAY_S_AXIS_ADDRESS 3
#define SCALE_MM (2560.0 / 25.4)
#define SCALE_INCH (2560.0)
#define IFRAME_TIMEDELAY (5 * 1000) /* ms */
// LedController seven_seg = LedController(12, 11, 10, DISPLAY_COUNT, false);
LedController seven_seg = LedController(11, 13, 10, DISPLAY_COUNT, true);
bool iFrameTrigger = false; // Should we force a display and data update?
unsigned long iFrameLastTime = 0L; // The last time we forced a data push to serial
// TODO: Factor out Switch Ports to a #define
#define ANALOG_BUTTON_COUNT 3
#define ANALOG_DEBOUNCE_TIME 100
#define ANALOG_IGNORE_TIME 500
#define ANALOG_HIGH_SW_LEVEL 855
#define ANALOG_MED_SW_LEVEL 515
#define ANALOG_LOW_SW_LEVEL 170
typedef enum {
button_none = 0x000,
button_x_zero = 0x001,
button_y_zero = 0x002,
button_z_zero = 0x004,
button_w_zero = 0x008,
button_x_absinc = 0x010,
button_y_absinc = 0x020,
button_z_absinc = 0x040,
button_w_absinc = 0x080,
button_up = 0x100,
button_select = 0x200,
button_down = 0x400
} _interface_buttons;
#define SUBMODE_TIMEOUT (15 * 1000) // 15 seconds
#define BLINK_TIME (250) // millis
int buttonInputPins[ANALOG_BUTTON_COUNT] = { A0, A1, A2 }; // Pins to configure as analog decoded button inputs
_interface_buttons lastButtons = 0; // The last button set we saw. To keep from repeating ourselves
unsigned long lastButtonTime = 0L;
typedef enum { // state machine for UI and operations
invalid_state = 0, // unset state.
show_values, // normal operating mode
show_menu, // show the config menu (> when in show_values)
set_axis_count, // set the counts per inch for axis
set_brightness, // setting brightness
set_precision, // set the display precision (number of decimal places)
set_units, // set the display units (inch or mm)
reverse_axis, // reverse axis orientation (+/-)
set_axis_half, // setting an axis to 1/2 value, select axis (+ when in show_values)
set_axis_value, // set axis to a specific value
zero_all, // zero all axes (- when in show_values)
restart_dro, // restart dro
reset_all, // reset all settings to defaults and restart
} _state;
_state lastState;
_state currentState; // current state of our UI state machine
typedef struct {
const char *title;
_state state;
} _menu;
/* the ordering of the menu items is really just my prefernece and
* predisposition to hit the down button when thinking of non-saved
* settings. So there's no real logic or reason here.
* menuSelected gets set to the first non-saved setting 1/2 axis
* again, just as my preference and thought this will be the most used
* selection.
*/
_menu menu[] = {
{ "CPI", set_axis_count },
{ "bright", set_brightness },
{ "digits", set_precision },
{ "units", set_axis_half },
{ "reverse", reverse_axis },
/* saved settings above this point, UP to get to them */
/* not saved settings below this point DOWN to get to them*/
{ "1-2 axis", set_axis_half },
{ "set value", set_axis_value },
{ "zero all", zero_all },
{ "restart", restart_dro },
{ "reset", reset_all },
{ "boobies", show_values },
};
int menuSelected = 5;
typedef enum {
units_inch = 0,
units_mm
} _display_units;
/* Settings that get saved in EEPROM to be restored on restart */
#define SETTINGS_MAGIC_VERSION 0x02
#define SETTINGS_MAGIC_ADDRESS 0
#define SETTINGS_EEPROM_ADDRESS 1
#define SETTINGS_BRIGHT_MASK 0x0F
#define SETTINGS_PRECISION_MASK 0xF0
#define SETTINGS_X_BIT 0
#define SETTINGS_Y_BIT 1
#define SETTINGS_Z_BIT 2
#define SETTINGS_W_BIT 3
#define SETTINGS_S_BIT 4
struct _saved_settings {
byte precision_brightness; // brightness in lower nybble, precision in upper (0-15)
byte axis_enabled; // x x x S W Z Y X -- 1 enabled, 0-disabled
byte orientation; // x x x S W Z Y X -- 1=revrse, 0=normal
byte units; // x x x S W Z Y X -- 1=metric, 0=imperial
unsigned int xCountPerInch; // number of counts per inch for X axis (2^16)
unsigned int yCountPerInch; // number of counts per inch for Y axis (2^16)
unsigned int zCountPerInch; // number of counts per inch for Z axis (2^16)
unsigned int wCountPerInch; // number of counts per inch for W axis (2^16)
unsigned int sCountPerRevolution; // number of counts per revolution for spindle (2^16)
};
struct _saved_settings droSettings;
void resetSettings() {
droSettings.precision_brightness = 0x43; // precision -4, brightness 3
droSettings.axis_enabled = 0x17; // Spindle, Z, Y, and X enabled
droSettings.orientation = 0x00; // All oriented to whatever scale reads
droSettings.units = 0x00; // All using inches
droSettings.xCountPerInch = 2560; // default for iGaging EZView scale
droSettings.yCountPerInch = 2560; // default for iGaging EZView scale
droSettings.zCountPerInch = 2560; // default for iGaging EZView scale
droSettings.wCountPerInch = 2560; // default for iGaging EZView scale
droSettings.sCountPerRevolution = 1; // default for iGaging EZView scale
EEPROM.put(SETTINGS_EEPROM_ADDRESS, droSettings);
}
void loadSettings() {
if (checkSettings()) {
EEPROM.get(SETTINGS_EEPROM_ADDRESS, droSettings);
} else {
resetSettings();
}
}
void saveSettings() {
EEPROM.put(SETTINGS_MAGIC_ADDRESS, SETTINGS_MAGIC_VERSION);
EEPROM.put(SETTINGS_EEPROM_ADDRESS, droSettings);
}
bool checkSettings() {
return EEPROM.read(SETTINGS_MAGIC_ADDRESS) == SETTINGS_MAGIC_VERSION;
}
inline int displayBrightness() {
return droSettings.precision_brightness & SETTINGS_BRIGHT_MASK;
}
inline void setDisplayBrightness(int bright) {
droSettings.precision_brightness = (droSettings.precision_brightness & ~SETTINGS_BRIGHT_MASK)
| (bright & SETTINGS_BRIGHT_MASK);
saveSettings();
}
inline int displayPrecision() {
// bias is 8 for negative numbers
return ((droSettings.precision_brightness >> 4) & 0x0F) - 8;
}
inline void setDisplayPrecision(int precision) {
droSettings.precision_brightness = (droSettings.precision_brightness & ~SETTINGS_PRECISION_MASK)
| (((precision + 8) << 4) & SETTINGS_PRECISION_MASK);
saveSettings();
}
inline bool axisEnabled(unsigned int axisBit) {
return bitRead(droSettings.axis_enabled, axisBit);
}
inline void setAxisEnabled(bool enabled, unsigned int axisBit) {
if (enabled) {
bitSet(droSettings.axis_enabled, axisBit);
} else {
bitClear(droSettings.axis_enabled, axisBit);
}
saveSettings();
}
inline bool xAxisEnabled() {
return axisEnabled(SETTINGS_X_BIT);
}
inline void setXAxisEnabled(bool enabled) {
setAxisEnabled(enabled, SETTINGS_X_BIT);
}
inline bool yAxisEnabled() {
return axisEnabled(SETTINGS_Y_BIT);
}
inline void setYAxisEnabled(bool enabled) {
setAxisEnabled(enabled, SETTINGS_Y_BIT);
}
inline bool zAxisEnabled() {
return axisEnabled(SETTINGS_Z_BIT);
}
inline void setZAxisEnabled(bool enabled) {
setAxisEnabled(enabled, SETTINGS_Z_BIT);
}
inline bool wAxisEnabled() {
return axisEnabled(SETTINGS_W_BIT);
}
inline void setWAxisEnabled(bool enabled) {
setAxisEnabled(enabled, SETTINGS_W_BIT);
}
inline bool sAxisEnabled() {
return axisEnabled(SETTINGS_S_BIT);
}
inline void setSAxisEnabled(bool enabled) {
setAxisEnabled(enabled, SETTINGS_S_BIT);
}
inline bool axisReversed(unsigned int axisBit) {
return bitRead(droSettings.orientation, axisBit);
}
inline void setAxisReversed(bool reversed, unsigned int axisBit) {
if (reversed) {
bitSet(droSettings.orientation, axisBit);
} else {
bitClear(droSettings.orientation, axisBit);
}
saveSettings();
}
inline bool xAxisReversed() {
return axisReversed(SETTINGS_X_BIT);
}
inline void setXAxisReversed(bool reversed) {
setAxisReversed(reversed, SETTINGS_X_BIT);
}
inline bool yAxisReversed() {
return axisReversed(SETTINGS_Y_BIT);
}
inline void setYAxisReversed(bool reversed) {
setAxisReversed(reversed, SETTINGS_Y_BIT);
}
inline bool zAxisReversed() {
return axisReversed(SETTINGS_Z_BIT);
}
inline void setZAxisReversed(bool reversed) {
setAxisReversed(reversed, SETTINGS_Z_BIT);
}
inline bool wAxisReversed() {
return axisReversed(SETTINGS_W_BIT);
}
inline void setWAxisReversed(bool reversed) {
setAxisReversed(reversed, SETTINGS_W_BIT);
}
inline bool sAxisReversed() {
return axisReversed(SETTINGS_S_BIT);
}
inline void setSAxisReversed(bool reversed) {
setAxisReversed(reversed, SETTINGS_S_BIT);
}
_display_units displayUnits() {
// TODO: Allow independently settable units rather than just using the X for them all.
return bitRead(droSettings.units, SETTINGS_X_BIT) ? units_inch : units_mm;
}
void setDisplayUnits(_display_units units) {
// TODO: Allow independently settable units rather than just using the X for them all.
if (units == units_mm) {
bitSet(droSettings.units, SETTINGS_X_BIT);
} else {
bitClear(droSettings.units, SETTINGS_X_BIT);
}
saveSettings();
}
inline int xCountPerInch() {
return droSettings.xCountPerInch;
}
inline int yCountPerInch() {
return droSettings.yCountPerInch;
}
inline int zCountPerInch() {
return droSettings.zCountPerInch;
}
inline int wCountPerInch() {
return droSettings.wCountPerInch;
}
inline int sCountPerRevolution() {
return droSettings.sCountPerRevolution;
}
/* === Display DRO === */
// DRO config (if axis is not connected change in the corresponding constant value from "1" to "0")
#define SCALE_X_ENABLED 1
#define SCALE_Y_ENABLED 1
#define SCALE_Z_ENABLED 1
#define SCALE_W_ENABLED 0
// DRO config (if axis is connected to Quadrature Encoder scales through LS7366R-type shield change in the corresponding constant value from "0" to "1")
#define SCALE_X_TYPE 0
#define SCALE_Y_TYPE 0
#define SCALE_Z_TYPE 0
#define SCALE_W_TYPE 0
// I/O ports config (change pin numbers if DRO, Tach sensor or Tach LED feedback is connected to different ports)
#define SCALE_CLK_PIN 2
#define SCALE_X_PIN 3
#define SCALE_Y_PIN 4
#define SCALE_Z_PIN 5
#define SCALE_W_PIN 6
// DRO rounding On/Off (if not enabled change in the corresponding constant value from "1" to "0")
#define SCALE_X_AVERAGE_ENABLED 1
#define SCALE_Y_AVERAGE_ENABLED 1
#define SCALE_Z_AVERAGE_ENABLED 1
#define SCALE_W_AVERAGE_ENABLED 1
// DRO rounding sample size. Change it to 16 for machines with power feed
#define AXIS_AVERAGE_COUNT 24
// Tach config (if Tach is not connected change in the corresponding constant value from "1" to "0")
#define TACH_ENABLED 1
#define INPUT_TACH_PIN 8
// Tach pre-scale value (number of tach sensor pulses per revolution)
#define TACH_PRESCALE 4
// Number of tach measurements to average
#define TACH_AVERAGE_COUNT 6
// This is rounding for tachometer display (set to 0 to disable or 1 for 1% rounding)
#define TACH_ROUND 0
// Tach data format
#define TACH_RAW_DATA_FORMAT 0 // single value format: T<rpm>;
// Tach RPM config
#define MIN_RPM_DELAY 1200 // 1.2 sec calculates to low range = 50 rpm.
// Tach LED feadback configmm
#define OUTPUT_TACH_LED_ENABLED 0
#define OUTPUT_TACH_LED_PIN 9
// Touch probe config (if Touch Probe is not connected change in the corresponding constant value from "1" to "0")
#define PROBE_ENABLED 0
#define INPUT_PROBE_PIN 8 // Pin 8 connected to Touch Probe
// Touch probe invert signal config
#define PROBE_INVERT 0 // Touch Probe signal inversion: Open = Input pin is Low; Closed = Input pin is High
// Touch probe LED feadback config
#define OUTPUT_PROBE_LED_ENABLED 1
#define OUTPUT_PROBE_LED_PIN 10 // When Quadrature Encoder scale are not used, on Arduino Uno you may change it to on-board LED pin 13.
// General Settings
#define UART_BAUD_RATE 9600 // Set this so it matches the BT module's BAUD rate
#define UPDATE_FREQUENCY 24 // Frequency in Hz (number of timer per second the scales are read and the data is sent to the application)
#define TACH_UPDATE_FREQUENCY 4 // Max Frequency in Hz (number of timer per second) the tach output is sent to the application
//---END OF CONFIGURATION PARAMETERS ---
//---DO NOT CHANGE THE CODE BELOW UNLESS YOU KNOW WHAT YOU ARE DOING ---
/* iGaging Clock Settings (do not change) */
#define SCALE_CLK_PULSES 21 // iGaging and Accuremote scales use 21 bit format
#define SCALE_CLK_FREQUENCY 9000 // iGaging scales run at about 9-10KHz
#define SCALE_CLK_DUTY 20 // iGaging scales clock run at 20% PWM duty (22us = ON out of 111us cycle)
/* weighted average constants */
#define FILTER_SLOW_EMA AXIS_AVERAGE_COUNT // Slow movement EMA
#define FILTER_FAST_EMA 2 // Fast movement EMA
#if (SCALE_X_ENABLED > 0) || (SCALE_Y_ENABLED > 0) || (SCALE_Z_ENABLED > 0) || (SCALE_W_ENABLED > 0)
#define DRO_ENABLED 1
#else
#define DRO_ENABLED 0
#endif
#if (SCALE_X_ENABLED > 0 && SCALE_X_TYPE == 0) || (SCALE_Y_ENABLED > 0 && SCALE_Y_TYPE == 0) || (SCALE_Z_ENABLED > 0 && SCALE_Z_TYPE == 0) || (SCALE_W_ENABLED > 0 && SCALE_W_TYPE == 0)
#define DRO_TYPE0_ENABLED 1
#else
#define DRO_TYPE0_ENABLED 0
#endif
#if (SCALE_X_ENABLED > 0 && SCALE_X_TYPE == 1) || (SCALE_Y_ENABLED > 0 && SCALE_Y_TYPE == 1) || (SCALE_Z_ENABLED > 0 && SCALE_Z_TYPE == 1) || (SCALE_W_ENABLED > 0 && SCALE_W_TYPE == 1)
#define DRO_TYPE1_ENABLED 1
#else
#define DRO_TYPE1_ENABLED 0
#endif
#if (SCALE_X_AVERAGE_ENABLED > 0) || (SCALE_Y_AVERAGE_ENABLED > 0) || (SCALE_Z_AVERAGE_ENABLED > 0) || (SCALE_W_AVERAGE_ENABLED > 0)
#define SCALE_AVERAGE_ENABLED 1
#else
#define SCALE_AVERAGE_ENABLED 0
#endif
// Define registers and pins for scale ports
#if SCALE_CLK_PIN < 8
#define CLK_PIN_BIT SCALE_CLK_PIN
#define SCALE_CLK_DDR DDRD
#define SCALE_CLK_OUTPUT_PORT PORTD
#else
#define CLK_PIN_BIT (SCALE_CLK_PIN - 8)
#define SCALE_CLK_DDR DDRB
#define SCALE_CLK_OUTPUT_PORT PORTB
#endif
#if SCALE_X_PIN < 8
#define X_PIN_BIT SCALE_X_PIN
#define X_DDR DDRD
#define X_INPUT_PORT PIND
#define X_OUTPUT_PORT PORTD
#else
#define X_PIN_BIT (SCALE_X_PIN - 8)
#define X_DDR DDRB
#define X_INPUT_PORT PINB
#define X_OUTPUT_PORT PORTB
#endif
#if SCALE_Y_PIN < 8
#define Y_PIN_BIT SCALE_Y_PIN
#define Y_DDR DDRD
#define Y_INPUT_PORT PIND
#define Y_OUTPUT_PORT PORTD
#else
#define Y_PIN_BIT (SCALE_Y_PIN - 8)
#define Y_DDR DDRB
#define Y_INPUT_PORT PINB
#define Y_OUTPUT_PORT PORTB
#endif
#if SCALE_Z_PIN < 8
#define Z_PIN_BIT SCALE_Z_PIN
#define Z_DDR DDRD
#define Z_INPUT_PORT PIND
#define Z_OUTPUT_PORT PORTD
#else
#define Z_PIN_BIT (SCALE_Z_PIN - 8)
#define Z_DDR DDRB
#define Z_INPUT_PORT PINB
#define Z_OUTPUT_PORT PORTB
#endif
#if SCALE_W_PIN < 8
#define W_PIN_BIT SCALE_W_PIN
#define W_DDR DDRD
#define W_INPUT_PORT PIND
#define W_OUTPUT_PORT PORTD
#else
#define W_PIN_BIT (SCALE_W_PIN - 8)
#define W_DDR DDRB
#define W_INPUT_PORT PINB
#define W_OUTPUT_PORT PORTB
#endif
// Define tach interrupt for selected pin
#if INPUT_TACH_PIN == 2
#define TACH_PIN_BIT 2
#define TACH_DDR DDRD
#define TACH_INPUT_PORT PIND
#define TACH_INTERRUPT_VECTOR PCINT2_vect
#define TACH_INTERRUPT_REGISTER PCIE2
#define TACH_INTERRUPT_MASK PCMSK2
#define TACH_INTERRUPT_PIN PCINT18
#elif INPUT_TACH_PIN == 3
#define TACH_PIN_BIT 3
#define TACH_DDR DDRD
#define TACH_INPUT_PORT PIND
#define TACH_INTERRUPT_VECTOR PCINT2_vect
#define TACH_INTERRUPT_REGISTER PCIE2
#define TACH_INTERRUPT_MASK PCMSK2
#define TACH_INTERRUPT_PIN PCINT19
#elif INPUT_TACH_PIN == 4
#define TACH_PIN_BIT 4
#define TACH_DDR DDRD
#define TACH_INPUT_PORT PIND
#define TACH_INTERRUPT_VECTOR PCINT2_vect
#define TACH_INTERRUPT_REGISTER PCIE2
#define TACH_INTERRUPT_MASK PCMSK2
#define TACH_INTERRUPT_PIN PCINT20
#elif INPUT_TACH_PIN == 5
#define TACH_PIN_BIT 5
#define TACH_DDR DDRD
#define TACH_INPUT_PORT PIND
#define TACH_INTERRUPT_VECTOR PCINT2_vect
#define TACH_INTERRUPT_REGISTER PCIE2
#define TACH_INTERRUPT_MASK PCMSK2
#define TACH_INTERRUPT_PIN PCINT21
#elif INPUT_TACH_PIN == 6
#define TACH_PIN_BIT 6
#define TACH_DDR DDRD
#define TACH_INPUT_PORT PIND
#define TACH_INTERRUPT_VECTOR PCINT2_vect
#define TACH_INTERRUPT_REGISTER PCIE2
#define TACH_INTERRUPT_MASK PCMSK2
#define TACH_INTERRUPT_PIN PCINT22
#elif INPUT_TACH_PIN == 7
#define TACH_PIN_BIT 7
#define TACH_DDR DDRD
#define TACH_INPUT_PORT PIND
#define TACH_INTERRUPT_VECTOR PCINT2_vect
#define TACH_INTERRUPT_REGISTER PCIE2
#define TACH_INTERRUPT_MASK PCMSK2
#define TACH_INTERRUPT_PIN PCINT23
#elif INPUT_TACH_PIN == 8
#define TACH_PIN_BIT 0
#define TACH_DDR DDRB
#define TACH_INPUT_PORT PINB
#define TACH_INTERRUPT_VECTOR PCINT0_vect
#define TACH_INTERRUPT_REGISTER PCIE0
#define TACH_INTERRUPT_MASK PCMSK0
#define TACH_INTERRUPT_PIN PCINT0
#elif INPUT_TACH_PIN == 9
#define TACH_PIN_BIT 1
#define TACH_DDR DDRB
#define TACH_INPUT_PORT PINB
#define TACH_INTERRUPT_VECTOR PCINT0_vect
#define TACH_INTERRUPT_REGISTER PCIE0
#define TACH_INTERRUPT_MASK PCMSK0
#define TACH_INTERRUPT_PIN PCINT1
#elif INPUT_TACH_PIN == 10
#define TACH_PIN_BIT 2
#define TACH_DDR DDRB
#define TACH_INPUT_PORT PINB
#define TACH_INTERRUPT_VECTOR PCINT0_vect
#define TACH_INTERRUPT_REGISTER PCIE0
#define TACH_INTERRUPT_MASK PCMSK0
#define TACH_INTERRUPT_PIN PCINT2
#elif INPUT_TACH_PIN == 11
#define TACH_PIN_BIT 3
#define TACH_DDR DDRB
#define TACH_INPUT_PORT PINB
#define TACH_INTERRUPT_VECTOR PCINT0_vect
#define TACH_INTERRUPT_REGISTER PCIE0
#define TACH_INTERRUPT_MASK PCMSK0
#define TACH_INTERRUPT_PIN PCINT3
#elif INPUT_TACH_PIN == 12
#define TACH_PIN_BIT 4
#define TACH_DDR DDRB
#define TACH_INPUT_PORT PINB
#define TACH_INTERRUPT_VECTOR PCINT0_vect
#define TACH_INTERRUPT_REGISTER PCIE0
#define TACH_INTERRUPT_MASK PCMSK0
#define TACH_INTERRUPT_PIN PCINT4
#elif INPUT_TACH_PIN == 13
#define TACH_PIN_BIT 5
#define TACH_DDR DDRB
#define TACH_INPUT_PORT PINB
#define TACH_INTERRUPT_VECTOR PCINT0_vect
#define TACH_INTERRUPT_REGISTER PCIE0
#define TACH_INTERRUPT_MASK PCMSK0
#define TACH_INTERRUPT_PIN PCINT5
#endif
#if OUTPUT_TACH_LED_PIN < 8
#define TACH_LED_PIN_BIT OUTPUT_TACH_LED_PIN
#define TACH_LED_DDR DDRD
#define TACH_LED_OUTPUT_PORT PORTD
#else
#define TACH_LED_PIN_BIT (OUTPUT_TACH_LED_PIN - 8)
#define TACH_LED_DDR DDRB
#define TACH_LED_OUTPUT_PORT PORTB
#endif
// Define registers and pins for touch probe
#if INPUT_PROBE_PIN < 8
#define PROBE_PIN_BIT INPUT_PROBE_PIN
#define PROBE_DDR DDRD
#define PROBE_INPUT_PORT PIND
#else
#define PROBE_PIN_BIT (INPUT_PROBE_PIN - 8)
#define PROBE_DDR DDRB
#define PROBE_INPUT_PORT PINB
#endif
#if OUTPUT_PROBE_LED_PIN < 8
#define PROBE_LED_PIN_BIT OUTPUT_PROBE_LED_PIN
#define PROBE_LED_DDR DDRD
#define PROBE_LED_OUTPUT_PORT PORTD
#else
#define PROBE_LED_PIN_BIT (OUTPUT_PROBE_LED_PIN - 8)
#define PROBE_LED_DDR DDRB
#define PROBE_LED_OUTPUT_PORT PORTB
#endif
#if DRO_TYPE1_ENABLED
#include <SPI.h>
#endif
// Some constants calculated here
unsigned long const minRpmTime = (((long) MIN_RPM_DELAY) * ((long) 1000));
long const longMax = __LONG_MAX__;
long const longMin = (- __LONG_MAX__ - (long) 1);
long const slowSc = ((long) 2000) / (((long) FILTER_SLOW_EMA) + ((long) 1));
long const fastSc = ((long) 20) / (((long) FILTER_FAST_EMA) + ((long) 1));
#if TACH_UPDATE_FREQUENCY == UPDATE_FREQUENCY
int const tachUpdateFrequencyCounterLimit = 1;
#else
int const tachUpdateFrequencyCounterLimit = (((long) UPDATE_FREQUENCY) / ((long) TACH_UPDATE_FREQUENCY));
#endif
int const updateFrequencyCounterLimit = (int) (((unsigned long) SCALE_CLK_FREQUENCY) /((unsigned long) UPDATE_FREQUENCY));
int const clockCounterLimit = (int) (((unsigned long) (F_CPU/8)) / (unsigned long) SCALE_CLK_FREQUENCY) - 10;
int const scaleClockDutyLimit = (int) (((unsigned long) (F_CPU/800)) * ((unsigned long) SCALE_CLK_DUTY) / (unsigned long) SCALE_CLK_FREQUENCY);
int const scaleClockFirstReadDelay = (int) ((unsigned long) F_CPU/4000000);
//variables that will store tach info and status
volatile unsigned long tachInterruptTimer;
volatile unsigned long tachInterruptRotationCount;
volatile unsigned long tachTimerStart;
//variables that will store the readout output
volatile unsigned long tachReadoutRotationCount;
volatile unsigned long tachReadoutMicrosec;
volatile unsigned long tachReadoutRpm;
unsigned long lastTachReadoutRpm;
#if TACH_AVERAGE_COUNT > 1
volatile unsigned long tachLastRead[TACH_AVERAGE_COUNT];
volatile int tachLastReadPosition;
#endif
volatile int tachUpdateFrequencyCounter;
volatile boolean sendTachData;
// variable to store the touch probe status.
volatile unsigned int probeReportedValue;
//variables that will store the DRO readout
volatile boolean tickTimerFlag;
volatile int updateFrequencyCounter;
// Axis count
#if SCALE_X_ENABLED > 0
volatile long xValue;
volatile long xReportedValue;
long xLastReportedValue;
long xZeroSetValue;
bool xAbsMode;
#endif
#if SCALE_X_AVERAGE_ENABLED > 0
volatile long axisLastReadX[AXIS_AVERAGE_COUNT];
volatile int axisLastReadPositionX;
volatile long axisAMAValueX;
#endif
#if SCALE_Y_ENABLED > 0
volatile long yValue;
volatile long yReportedValue;
long yLastReportedValue;
long yZeroSetValue;
bool yAbsMode;
#endif
#if SCALE_Y_AVERAGE_ENABLED > 0
volatile long axisLastReadY[AXIS_AVERAGE_COUNT];
volatile int axisLastReadPositionY;
volatile long axisAMAValueY;
#endif
#if SCALE_Z_ENABLED > 0
volatile long zValue;
volatile long zReportedValue;
long zLastReportedValue;
long zZeroSetValue;
bool zAbsMode;
#endif
#if SCALE_Z_AVERAGE_ENABLED > 0
volatile long axisLastReadZ[AXIS_AVERAGE_COUNT];
volatile int axisLastReadPositionZ;
volatile long axisAMAValueZ;
#endif
#if SCALE_W_ENABLED > 0
volatile long wValue;
volatile long wReportedValue;
long wLastReportedValue;
long wZeroSetValue;
bool wAbsMode;
#endif
#if SCALE_W_AVERAGE_ENABLED > 0
volatile long axisLastReadW[AXIS_AVERAGE_COUNT];
volatile int axisLastReadPositionW;
volatile long axisAMAValueW;
#endif