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 = + - - + - - - + - - - - - -