From 363a17ac464e72bb013150e742b0e95f9df707eb Mon Sep 17 00:00:00 2001
From: Stuart Pittaway <1201909+stuartpittaway@users.noreply.github.com>
Date: Sat, 4 Dec 2021 23:44:10 +0000
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20M3426=20to=20read=20i2c=20MCP3426?=
=?UTF-8?q?=20ADC=20(#23184)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Marlin/src/feature/adc/adc_mcp3426.cpp | 104 +++++++++++++++++++++
Marlin/src/feature/adc/adc_mcp3426.h | 41 ++++++++
Marlin/src/feature/twibus.cpp | 15 ++-
Marlin/src/gcode/feature/adc/M3426.cpp | 63 +++++++++++++
Marlin/src/gcode/gcode.cpp | 4 +
Marlin/src/gcode/gcode.h | 5 +
Marlin/src/pins/stm32f4/pins_INDEX_REV03.h | 5 +
ini/features.ini | 1 +
platformio.ini | 1 +
9 files changed, 234 insertions(+), 5 deletions(-)
create mode 100644 Marlin/src/feature/adc/adc_mcp3426.cpp
create mode 100644 Marlin/src/feature/adc/adc_mcp3426.h
create mode 100644 Marlin/src/gcode/feature/adc/M3426.cpp
diff --git a/Marlin/src/feature/adc/adc_mcp3426.cpp b/Marlin/src/feature/adc/adc_mcp3426.cpp
new file mode 100644
index 0000000000..aaddf46821
--- /dev/null
+++ b/Marlin/src/feature/adc/adc_mcp3426.cpp
@@ -0,0 +1,104 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 .
+ *
+ */
+
+/**
+ * adc_mcp3426.cpp - library for MicroChip MCP3426 I2C A/D converter
+ *
+ * For implementation details, please take a look at the datasheet:
+ * https://www.microchip.com/en-us/product/MCP3426
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(HAS_MCP3426_ADC)
+
+#include "adc_mcp3426.h"
+
+// Read the ADC value from MCP342X on a specific channel
+int16_t MCP3426::ReadValue(uint8_t channel, uint8_t gain) {
+ Error = false;
+
+ #if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM)
+ Wire.setSDA(pin_t(I2C_SDA_PIN));
+ Wire.setSCL(pin_t(I2C_SCL_PIN));
+ #endif
+
+ Wire.begin(); // No address joins the BUS as the master
+
+ Wire.beginTransmission(I2C_ADDRESS(MCP342X_ADC_I2C_ADDRESS));
+
+ // Continuous Conversion Mode, 16 bit, Channel 1, Gain x4
+ // 26 = 0b00011000
+ // RXXCSSGG
+ // R = Ready Bit
+ // XX = Channel (00=1, 01=2, 10=3 (MCP3428), 11=4 (MCP3428))
+ // C = Conversion Mode Bit (1= Continuous Conversion Mode (Default))
+ // SS = Sample rate, 10=15 samples per second @ 16 bits
+ // GG = Gain 00 =x1
+ uint8_t controlRegister = 0b00011000;
+
+ if (channel == 2) controlRegister |= 0b00100000; // Select channel 2
+
+ if (gain == 2)
+ controlRegister |= 0b00000001;
+ else if (gain == 4)
+ controlRegister |= 0b00000010;
+ else if (gain == 8)
+ controlRegister |= 0b00000011;
+
+ Wire.write(controlRegister);
+ if (Wire.endTransmission() != 0) {
+ Error = true;
+ return 0;
+ }
+
+ const uint8_t len = 3;
+ uint8_t buffer[len] = {};
+
+ do {
+ Wire.requestFrom(I2C_ADDRESS(MCP342X_ADC_I2C_ADDRESS), len);
+ if (Wire.available() != len) {
+ Error = true;
+ return 0;
+ }
+
+ for (uint8_t i = 0; i < len; ++i)
+ buffer[i] = Wire.read();
+
+ // Is conversion ready, if not loop around again
+ } while ((buffer[2] & 0x80) != 0);
+
+ union TwoBytesToInt16 {
+ uint8_t bytes[2];
+ int16_t integervalue;
+ };
+ TwoBytesToInt16 ConversionUnion;
+
+ ConversionUnion.bytes[1] = buffer[0];
+ ConversionUnion.bytes[0] = buffer[1];
+
+ return ConversionUnion.integervalue;
+}
+
+MCP3426 mcp3426;
+
+#endif // HAS_MCP3426_ADC
diff --git a/Marlin/src/feature/adc/adc_mcp3426.h b/Marlin/src/feature/adc/adc_mcp3426.h
new file mode 100644
index 0000000000..35458716b9
--- /dev/null
+++ b/Marlin/src/feature/adc/adc_mcp3426.h
@@ -0,0 +1,41 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 .
+ *
+ */
+#pragma once
+
+/**
+ * Arduino library for MicroChip MCP3426 I2C A/D converter.
+ * https://www.microchip.com/en-us/product/MCP3426
+ */
+
+#include
+#include
+
+// Address of MCP342X chip
+#define MCP342X_ADC_I2C_ADDRESS 104
+
+class MCP3426 {
+ public:
+ int16_t ReadValue(uint8_t channel, uint8_t gain);
+ bool Error;
+};
+
+extern MCP3426 mcp3426;
diff --git a/Marlin/src/feature/twibus.cpp b/Marlin/src/feature/twibus.cpp
index e33581676c..bbe4c0966a 100644
--- a/Marlin/src/feature/twibus.cpp
+++ b/Marlin/src/feature/twibus.cpp
@@ -34,13 +34,18 @@ TWIBus i2c;
TWIBus::TWIBus() {
#if I2C_SLAVE_ADDRESS == 0
- Wire.begin( // No address joins the BUS as the master
- #if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM)
- pin_t(I2C_SDA_PIN), pin_t(I2C_SCL_PIN)
- #endif
- );
+
+ #if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM)
+ Wire.setSDA(pin_t(I2C_SDA_PIN));
+ Wire.setSCL(pin_t(I2C_SCL_PIN));
+ #endif
+
+ Wire.begin(); // No address joins the BUS as the master
+
#else
+
Wire.begin(I2C_SLAVE_ADDRESS); // Join the bus as a slave
+
#endif
reset();
}
diff --git a/Marlin/src/gcode/feature/adc/M3426.cpp b/Marlin/src/gcode/feature/adc/M3426.cpp
new file mode 100644
index 0000000000..8205fa01f2
--- /dev/null
+++ b/Marlin/src/gcode/feature/adc/M3426.cpp
@@ -0,0 +1,63 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 .
+ *
+ */
+
+#include "../../../inc/MarlinConfig.h"
+
+#if ENABLED(HAS_MCP3426_ADC)
+
+#include "../../gcode.h"
+
+#include "../../../feature/adc/adc_mcp3426.h"
+
+/**
+ * M3426: Read 16 bit (signed) value from I2C MCP3426 ADC device
+ *
+ * M3426 C channel 1 or 2
+ * M3426 G gain 1, 2, 4 or 8
+ * M3426 I 0 or 1, invert reply
+ */
+void GcodeSuite::M3426() {
+ uint8_t channel = parser.byteval('C', 1), // Select the channel 1 or 2
+ gain = parser.byteval('G', 1);
+ const bool inverted = parser.byteval('I') == 1;
+
+ if (channel <= 2 && (gain == 1 || gain == 2 || gain == 4 || gain == 8)) {
+ int16_t result = mcp3426.ReadValue(channel, gain);
+
+ if (mcp3426.Error == false) {
+ if (inverted) {
+ // Should we invert the reading (32767 - ADC value) ?
+ // Caters to end devices that expect values to increase when in reality they decrease.
+ // e.g., A pressure sensor in a vacuum when the end device expects a positive pressure.
+ result = INT16_MAX - result;
+ }
+ //SERIAL_ECHOPGM(STR_OK);
+ SERIAL_ECHOLNPGM("V:", result, " C:", channel, " G:", gain, " I:", inverted ? 1 : 0);
+ }
+ else
+ SERIAL_ERROR_MSG("MCP342X i2c error");
+ }
+ else
+ SERIAL_ERROR_MSG("MCP342X Bad request");
+}
+
+#endif // HAS_MCP3426_ADC
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index 24eb9914d1..c05ac5494d 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -1054,6 +1054,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 7219: M7219(); break; // M7219: Set LEDs, columns, and rows
#endif
+ #if ENABLED(HAS_MCP3426_ADC)
+ case 3426: M3426(); break; // M3426: Read MCP3426 ADC (over i2c)
+ #endif
+
default: parser.unknown_command_warning(); break;
}
break;
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 6bfaf00c13..bbfb31a3fe 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -297,6 +297,7 @@
* M917 - L6470 tuning: Find minimum current thresholds. (Requires at least one _DRIVER_TYPE L6470)
* M918 - L6470 tuning: Increase speed until max or error. (Requires at least one _DRIVER_TYPE L6470)
* M951 - Set Magnetic Parking Extruder parameters. (Requires MAGNETIC_PARKING_EXTRUDER)
+ * M3426 - Read MCP3426 ADC over I2C. (Requires HAS_MCP3426_ADC)
* M7219 - Control Max7219 Matrix LEDs. (Requires MAX7219_GCODE)
*
*** SCARA ***
@@ -1204,6 +1205,10 @@ private:
static void M1004();
#endif
+ #if ENABLED(HAS_MCP3426_ADC)
+ static void M3426();
+ #endif
+
#if ENABLED(MAX7219_GCODE)
static void M7219();
#endif
diff --git a/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h b/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h
index 8761ca955a..8560a04375 100644
--- a/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h
+++ b/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h
@@ -42,6 +42,9 @@
#define SRAM_EEPROM_EMULATION
#define MARLIN_EEPROM_SIZE 0x2000 // 8KB
+// I2C MCP3426 (16-Bit, 240SPS, dual-channel ADC)
+#define HAS_MCP3426_ADC
+
//
// Servos
//
@@ -116,6 +119,8 @@
#define FAN2_PIN PE4
#define FAN3_PIN PE5
+#define FAN_SOFT_PWM
+
// Neopixel Rings
#define NEOPIXEL_PIN PC7
#define NEOPIXEL2_PIN PC8
diff --git a/ini/features.ini b/ini/features.ini
index 91baa601ca..b56565b154 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -94,6 +94,7 @@ NEXTION_TFT = src_filter=+
USE_UHS2_USB = src_filter=+
USE_UHS3_USB = src_filter=+
USB_FLASH_DRIVE_SUPPORT = src_filter=+
+HAS_MCP3426_ADC = src_filter=+ +
AUTO_BED_LEVELING_BILINEAR = src_filter=+
AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+
MESH_BED_LEVELING = src_filter=+ +
diff --git a/platformio.ini b/platformio.ini
index 07821fca96..1b4effcf25 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -92,6 +92,7 @@ default_src_filter = + - - +
-
-
-
+ - -
-
-
- -