Bläddra i källkod

Add Laser Based I2C Ammeter Feature (#21835)

Mike La Spina 2 år sedan
förälder
incheckning
002e1d49fe
Inget konto är kopplat till bidragsgivarens mejladress

+ 9
- 0
Marlin/Configuration_adv.h Visa fil

@@ -3283,6 +3283,15 @@
3283 3283
     //#define AIR_ASSIST_PIN            44     // Override the default Air Assist pin
3284 3284
   #endif
3285 3285
 
3286
+  //
3287
+  // Laser I2C Ammeter (High precision INA226 low/high side module)
3288
+  //
3289
+  //#define I2C_AMMETER
3290
+  #if ENABLED(I2C_AMMETER)
3291
+    #define I2C_AMMETER_IMAX            .1     // Calibration value for the expected current range in Amps (use float e.g. 1.0)
3292
+    #define I2C_AMMETER_SHUNT_RESISTOR  .1     // Calibration shunt resistor value in ohms
3293
+  #endif
3294
+
3286 3295
   //#define SPINDLE_SERVO                      // A servo converting an angle to spindle power
3287 3296
   #ifdef SPINDLE_SERVO
3288 3297
     #define SPINDLE_SERVO_NR   0               // Index of servo used for spindle control

+ 49
- 0
Marlin/src/feature/ammeter.cpp Visa fil

@@ -0,0 +1,49 @@
1
+  /**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../inc/MarlinConfig.h"
24
+
25
+#if ENABLED(I2C_AMMETER)
26
+  #include "ammeter.h"
27
+
28
+  INA226 ina;
29
+
30
+  Ammeter ammeter;
31
+
32
+  float Ammeter::scale;
33
+  float Ammeter::current;
34
+
35
+  void Ammeter::init() {
36
+    ina.begin();
37
+    ina.configure(INA226_AVERAGES_16, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
38
+    ina.calibrate(I2C_AMMETER_SHUNT_RESISTOR,I2C_AMMETER_IMAX);
39
+  }
40
+
41
+  float Ammeter::read() {
42
+      scale = 1;
43
+      current = ina.readShuntCurrent();
44
+      if (current <= .0001) current = 0;  // Cleanup lsb bit amplification errors
45
+      if (current < .1) scale = 1000; 
46
+      return current * scale;
47
+  }
48
+
49
+#endif //I2C_AMMETER

+ 44
- 0
Marlin/src/feature/ammeter.h Visa fil

@@ -0,0 +1,44 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "../inc/MarlinConfigPre.h"
25
+
26
+#include <Wire.h>
27
+#include <INA226.h>
28
+
29
+#ifndef I2C_AMMETER_IMAX    
30
+  #define I2C_AMMETER_IMAX      .500 // Calibration range 500 Milli Amps
31
+#endif
32
+
33
+class Ammeter {
34
+private:
35
+    static float scale;
36
+
37
+public:
38
+    static float current;
39
+    static void init();
40
+    static float read();
41
+ 
42
+};
43
+
44
+extern Ammeter ammeter;

+ 8
- 0
Marlin/src/feature/spindle_laser.cpp Visa fil

@@ -34,6 +34,10 @@
34 34
   #include "../module/servo.h"
35 35
 #endif
36 36
 
37
+#if ENABLED(I2C_AMMETER)
38
+  #include "../feature/ammeter.h"
39
+#endif
40
+
37 41
 SpindleLaser cutter;
38 42
 uint8_t SpindleLaser::power;
39 43
 #if ENABLED(LASER_FEATURE)
@@ -74,6 +78,10 @@ void SpindleLaser::init() {
74 78
   #if ENABLED(AIR_ASSIST)
75 79
     OUT_WRITE(AIR_ASSIST_PIN, !AIR_ASSIST_ACTIVE);                    // Init Air Assist OFF
76 80
   #endif
81
+  #if ENABLED(I2C_AMMETER)
82
+    ammeter.init();                    // Init I2C Ammeter
83
+  #endif
84
+  
77 85
 }
78 86
 
79 87
 #if ENABLED(SPINDLE_LASER_PWM)

+ 22
- 1
Marlin/src/lcd/HD44780/marlinui_HD44780.cpp Visa fil

@@ -50,6 +50,10 @@
50 50
   #include "../../feature/cooler.h"
51 51
 #endif
52 52
 
53
+#if ENABLED(I2C_AMMETER)
54
+  #include "../../feature/ammeter.h"
55
+#endif
56
+
53 57
 #if ENABLED(AUTO_BED_LEVELING_UBL)
54 58
   #include "../../feature/bedlevel/bedlevel.h"
55 59
 #endif
@@ -588,12 +592,26 @@ FORCE_INLINE void _draw_cooler_status(const char prefix, const bool blink) {
588 592
 
589 593
 #if ENABLED(LASER_COOLANT_FLOW_METER)
590 594
   FORCE_INLINE void _draw_flowmeter_status() {
591
-    lcd_put_u8str("~ ");
595
+    lcd_put_u8str("~");
592 596
     lcd_put_u8str(ftostr11ns(cooler.flowrate));
593 597
     lcd_put_wchar('L');
594 598
   }
595 599
 #endif
596 600
 
601
+#if ENABLED(I2C_AMMETER)
602
+  FORCE_INLINE void _draw_ammeter_status() {
603
+    lcd_put_u8str(" ");
604
+    ammeter.read();
605
+    if (ammeter.current <= .999) {
606
+      lcd_put_u8str(ftostr3ns(ammeter.current));
607
+      lcd_put_u8str("mA");
608
+    } else {
609
+      lcd_put_u8str(ftostr12ns(ammeter.current));
610
+      lcd_put_wchar('A');
611
+    }
612
+  }
613
+#endif
614
+
597 615
 FORCE_INLINE void _draw_bed_status(const bool blink) {
598 616
   _draw_heater_status(H_BED, TERN0(HAS_LEVELING, blink && planner.leveling_active) ? '_' : LCD_STR_BEDTEMP[0], blink);
599 617
 }
@@ -835,6 +853,9 @@ void MarlinUI::draw_status_screen() {
835 853
       #if ENABLED(LASER_COOLANT_FLOW_METER)
836 854
         _draw_flowmeter_status();
837 855
       #endif
856
+      #if ENABLED(I2C_AMMETER)
857
+        _draw_ammeter_status();
858
+      #endif
838 859
 
839 860
     #endif // LCD_WIDTH >= 20
840 861
 

+ 41
- 1
Marlin/src/lcd/dogm/dogm_Statusscreen.h Visa fil

@@ -107,7 +107,18 @@
107 107
   #define STATUS_FLOWMETER_BYTEWIDTH BW(STATUS_FLOWMETER_WIDTH)
108 108
 #endif
109 109
 
110
-
110
+//
111
+// Laser Ammeter
112
+//
113
+#if !STATUS_AMMETER_WIDTH && ENABLED(I2C_AMMETER)
114
+  #include "status/ammeter.h"
115
+#endif
116
+#ifndef STATUS_AMMETER_WIDTH
117
+  #define STATUS_AMMETER_WIDTH 0
118
+#endif
119
+#ifndef STATUS_AMMETER_BYTEWIDTH
120
+  #define STATUS_AMMETER_BYTEWIDTH BW(STATUS_AMMETER_WIDTH)
121
+#endif
111 122
 
112 123
 //
113 124
 // Bed
@@ -603,6 +614,32 @@
603 614
   #endif
604 615
 #endif
605 616
 
617
+#if ENABLED(I2C_AMMETER)
618
+  #if STATUS_AMMETER_WIDTH
619
+
620
+    #ifndef STATUS_AMMETER_X
621
+      #define STATUS_AMMETER_X (LCD_PIXEL_WIDTH - (STATUS_AMMETER_BYTEWIDTH + STATUS_FLOWMETER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH + STATUS_COOLER_BYTEWIDTH) * 8)
622
+    #endif
623
+
624
+    #ifndef STATUS_AMMETER_HEIGHT
625
+      #define STATUS_AMMETER_HEIGHT(S) (sizeof(status_ammeter_bmp1) / (STATUS_AMMETER_BYTEWIDTH))
626
+    #endif
627
+
628
+    #ifndef STATUS_AMMETER_Y
629
+      #define STATUS_AMMETER_Y(S) (18 - STATUS_AMMETER_HEIGHT(S))
630
+    #endif
631
+
632
+    #ifndef STATUS_AMMETER_TEXT_X
633
+      #define STATUS_AMMETER_TEXT_X (STATUS_AMMETER_X + 7)
634
+    #endif
635
+
636
+    static_assert(
637
+      sizeof(status_ammeter_bmp1) == (STATUS_AMMETER_BYTEWIDTH) * STATUS_AMMETER_HEIGHT(0),
638
+      "Status ammeter bitmap (status_ammeter_bmp1) dimensions don't match data."
639
+    );
640
+  #endif
641
+#endif
642
+
606 643
 //
607 644
 // Bed Bitmap Properties
608 645
 //
@@ -696,6 +733,9 @@
696 733
 #if ENABLED(LASER_COOLANT_FLOW_METER)
697 734
   #define DO_DRAW_FLOWMETER 1
698 735
 #endif
736
+#if ENABLED(I2C_AMMETER)
737
+  #define DO_DRAW_AMMETER 1
738
+#endif
699 739
 
700 740
 #if HAS_TEMP_CHAMBER && STATUS_CHAMBER_WIDTH && HOTENDS <= 4
701 741
   #define DO_DRAW_CHAMBER 1

+ 71
- 0
Marlin/src/lcd/dogm/status/ammeter.h Visa fil

@@ -0,0 +1,71 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+//
25
+// lcd/dogm/status/ammeter.h - Status Screen Laser Ammeter bitmaps
26
+//
27
+#if ENABLED(I2C_AMMETER)
28
+
29
+  #define STATUS_AMMETER_WIDTH 20
30
+
31
+  const unsigned char status_ammeter_bmp_mA[] PROGMEM = {
32
+  B00000000,B11111100,B00000000,
33
+  B00000011,B00000011,B00000000,
34
+  B00000100,B00000000,B10000000,
35
+  B00001000,B00000000,B01000000,
36
+  B00010000,B00000110,B00100000,
37
+  B00010000,B00001001,B00100000,
38
+  B00100000,B00001001,B00010000,
39
+  B00100011,B01001111,B00010000,
40
+  B11100010,B10101001,B00011100,
41
+  B00100010,B10101001,B00010000,
42
+  B00100010,B10101001,B00010000,
43
+  B00010000,B00000000,B00100000,
44
+  B00010000,B00000000,B00100000,
45
+  B00001000,B00000000,B01000000,
46
+  B00000100,B00000000,B10000000,
47
+  B00000011,B00000011,B00000000,
48
+  B00000000,B11111100,B00000000
49
+  };
50
+
51
+const unsigned char status_ammeter_bmp_A[] PROGMEM = {
52
+  B00000000,B11111100,B00000000,
53
+  B00000011,B00000011,B00000000,
54
+  B00000100,B00000000,B10000000,
55
+  B00001000,B00000000,B01000000,
56
+  B00010000,B00000000,B00100000,
57
+  B00010000,B00110000,B00100000,
58
+  B00100000,B01001000,B00010000,
59
+  B00100000,B01001000,B00010000,
60
+  B11100000,B01111000,B00011100,
61
+  B00100000,B01001000,B00010000,
62
+  B00100000,B01001000,B00010000,
63
+  B00010000,B01001000,B00100000,
64
+  B00010000,B00000000,B00100000,
65
+  B00001000,B00000000,B01000000,
66
+  B00000100,B00000000,B10000000,
67
+  B00000011,B00000011,B00000000,
68
+  B00000000,B11111100,B00000000,
69
+};
70
+
71
+#endif

+ 32
- 32
Marlin/src/lcd/dogm/status/cooler.h Visa fil

@@ -29,40 +29,40 @@
29 29
   #define STATUS_COOLER_WIDTH 22
30 30
 
31 31
   const unsigned char status_cooler_bmp2[] PROGMEM = {
32
-    B00000100,B00000010,B00000000,
33
-    B00000100,B10010010,B01000000,
34
-    B00010101,B00001010,B10000000,
35
-    B00001110,B00000111,B00000000,
36
-    B00111111,B10111111,B11000000,
37
-    B00001110,B00000111,B00000000,
38
-    B00010101,B00001010,B10000000,
39
-    B00100100,B00100010,B01000000,
40
-    B00000100,B00100000,B00000000,
41
-    B00000001,B00100100,B00000000,
42
-    B00000000,B10101000,B00000000,
43
-    B00000000,B01110000,B00000000,
44
-    B00000111,B11111111,B00000000,
45
-    B00000000,B01110000,B00000000,
46
-    B00000000,B10101000,B00000000,
47
-    B00000001,B00100100,B00000000
32
+    B00000001,B00000000,B10000000,
33
+    B00000001,B00100100,B10010000,
34
+    B00000101,B01000010,B10100000,
35
+    B00000011,B10000001,B11000000,
36
+    B00001111,B11101111,B11110000,
37
+    B00000011,B10000001,B11000000,
38
+    B00000101,B01000010,B10100000,
39
+    B00001001,B00001000,B10010000,
40
+    B00000001,B00001000,B00000000,
41
+    B00000000,B01001001,B00000000,
42
+    B00000000,B00101010,B00000000,
43
+    B00000000,B00011100,B00000000,
44
+    B00000001,B11111111,B11000000,
45
+    B00000000,B00011100,B00000000,
46
+    B00000000,B00101010,B00000000,
47
+    B00000000,B01001001,B00000000
48 48
   };
49 49
   const unsigned char status_cooler_bmp1[] PROGMEM = {
50
-    B00000100,B00000010,B00000000,
51
-    B00000100,B10010010,B01000000,
52
-    B00010101,B00001010,B10000000,
53
-    B00001010,B00000101,B00000000,
54
-    B00110001,B11011000,B11000000,
55
-    B00001010,B00000101,B00000000,
56
-    B00010101,B00001010,B10000000,
57
-    B00100100,B00100010,B01000000,
58
-    B00000100,B00100000,B00000000,
59
-    B00000001,B00100100,B00000000,
60
-    B00000000,B10101000,B00000000,
61
-    B00000000,B01010000,B00000000,
62
-    B00000111,B10001111,B00000000,
63
-    B00000000,B01010000,B00000000,
64
-    B00000000,B10101000,B00000000,
65
-    B00000001,B00100100,B00000000
50
+    B00000001,B00000000,B10000000,
51
+    B00000001,B00100100,B10010000,
52
+    B00000101,B01000010,B10100000,
53
+    B00000010,B10000001,B01000000,
54
+    B00001100,B01110110,B00110000,
55
+    B00000010,B10000001,B01000000,
56
+    B00000101,B01000010,B10100000,
57
+    B00001001,B00001000,B10010000,
58
+    B00000001,B00001000,B00000000,
59
+    B00000000,B01001001,B00000000,
60
+    B00000000,B00101010,B00000000,
61
+    B00000000,B00010100,B00000000,
62
+    B00000001,B11100011,B11000000,
63
+    B00000000,B00010100,B00000000,
64
+    B00000000,B00101010,B00000000,
65
+    B00000000,B01001001,B00000000
66 66
   };
67 67
 
68 68
 #endif

+ 25
- 0
Marlin/src/lcd/dogm/status_screen_DOGM.cpp Visa fil

@@ -205,6 +205,14 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
205 205
   }
206 206
 #endif
207 207
 
208
+#if DO_DRAW_AMMETER
209
+  FORCE_INLINE void _draw_centered_current(const float current, const uint8_t tx, const uint8_t ty) {
210
+    const char *str = ftostr31ns(current);           
211
+    const uint8_t len = str[0] != ' ' ? 3 : str[1] != ' ' ? 2 : 1;
212
+    lcd_put_u8str(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty, &str[3-len]);
213
+  }
214
+#endif
215
+
208 216
 #if DO_DRAW_HOTENDS
209 217
 
210 218
   // Draw hotend bitmap with current and target temperatures
@@ -404,6 +412,13 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
404 412
   }
405 413
 #endif
406 414
 
415
+#if DO_DRAW_AMMETER
416
+  FORCE_INLINE void _draw_ammeter_status() {
417
+    if (PAGE_CONTAINS(28 - INFO_FONT_ASCENT, 28 - 1))
418
+      _draw_centered_current(ammeter.read(), STATUS_AMMETER_TEXT_X, 28);
419
+  }
420
+#endif
421
+
407 422
 //
408 423
 // Before homing, blink '123' <-> '???'.
409 424
 // Homed but unknown... '123' <-> '   '.
@@ -677,6 +692,13 @@ void MarlinUI::draw_status_screen() {
677 692
         u8g.drawBitmapP(STATUS_FLOWMETER_X, flowmetery, STATUS_FLOWMETER_BYTEWIDTH, flowmeterh, blink && cooler.flowpulses ? status_flowmeter_bmp2 : status_flowmeter_bmp1);
678 693
     #endif
679 694
 
695
+    // Laser Ammeter
696
+    #if DO_DRAW_AMMETER
697
+      const uint8_t ammetery = STATUS_AMMETER_Y(status_ammeter_bmp_mA),
698
+                    ammeterh = STATUS_AMMETER_HEIGHT(status_ammeter_bmp_mA);
699
+       if (PAGE_CONTAINS(ammetery, ammetery + ammeterh - 1))
700
+        u8g.drawBitmapP(STATUS_AMMETER_X, ammetery, STATUS_AMMETER_BYTEWIDTH, ammeterh, (ammeter.current < .1) ? status_ammeter_bmp_mA : status_ammeter_bmp_A);
701
+    #endif
680 702
 
681 703
     // Heated Bed
682 704
     TERN_(DO_DRAW_BED, _draw_bed_status(blink));
@@ -690,6 +712,9 @@ void MarlinUI::draw_status_screen() {
690 712
     // Flowmeter
691 713
     TERN_(DO_DRAW_FLOWMETER, _draw_flowmeter_status());
692 714
 
715
+    // Flowmeter
716
+    TERN_(DO_DRAW_AMMETER, _draw_ammeter_status());
717
+
693 718
     // Fan, if a bitmap was provided
694 719
     #if DO_DRAW_FAN
695 720
       if (PAGE_CONTAINS(STATUS_FAN_TEXT_Y - INFO_FONT_ASCENT, STATUS_FAN_TEXT_Y - 1)) {

+ 9
- 0
Marlin/src/libs/numtostr.cpp Visa fil

@@ -217,6 +217,15 @@ const char* ftostr41ns(const_float_t f) {
217 217
   return &conv[2];
218 218
 }
219 219
 
220
+// Convert unsigned float to string with 123 format
221
+const char* ftostr3ns(const_float_t f) {
222
+  const long i = UINTFLOAT(f, 3);
223
+  conv[4] = DIGIMOD(i, 100);
224
+  conv[5] = DIGIMOD(i, 10);
225
+  conv[6] = DIGIMOD(i, 1);
226
+  return &conv[4];
227
+}
228
+
220 229
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
221 230
 const char* ftostr42_52(const_float_t f) {
222 231
   if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45

+ 3
- 0
Marlin/src/libs/numtostr.h Visa fil

@@ -74,6 +74,9 @@ const char* ftostr31ns(const_float_t x);
74 74
 // Convert unsigned float to string with 123.4 format
75 75
 const char* ftostr41ns(const_float_t x);
76 76
 
77
+// Convert unsigned float to string with 123 format
78
+const char* ftostr3ns(const_float_t x);
79
+
77 80
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
78 81
 const char* ftostr42_52(const_float_t x);
79 82
 

+ 1
- 0
ini/features.ini Visa fil

@@ -30,6 +30,7 @@ HAS_L64XX                              = Arduino-L6470@0.8.0
30 30
 NEOPIXEL_LED                           = adafruit/Adafruit NeoPixel@~1.8.0
31 31
                                          src_filter=+<src/feature/leds/neopixel.cpp>
32 32
 TEMP_.+_IS_MAX31865                    = Adafruit MAX31865 library@~1.1.0
33
+I2C_AMMETER                            = peterus/INA226Lib@1.1.2
33 34
 USES_LIQUIDCRYSTAL                     = fmalpartida/LiquidCrystal@1.5.0
34 35
 USES_LIQUIDCRYSTAL_I2C                 = marcoschwartz/LiquidCrystal_I2C@1.1.4
35 36
 USES_LIQUIDTWI2                        = LiquidTWI2@1.2.7

Laddar…
Avbryt
Spara