Digipots refactor / cleanup (#19690)
This commit is contained in:
		| @@ -154,7 +154,7 @@ void Stepper::digipot_init() { | ||||
|   NVIC_SetPriority(PWM_IRQn, NVIC_EncodePriority(0, 10, 0));  // normal priority for PWM module (can stand some jitter on the Vref signals) | ||||
| } | ||||
|  | ||||
| void Stepper::digipot_current(const uint8_t driver, const int16_t current) { | ||||
| void Stepper::set_digipot_current(const uint8_t driver, const int16_t current) { | ||||
|  | ||||
|   if (!(PWM->PWM_CH_NUM[0].PWM_CPRD == PWM_PERIOD_US)) digipot_init();  // Init PWM system if needed | ||||
|  | ||||
|   | ||||
| @@ -191,7 +191,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o | ||||
| // | ||||
| // Flag any i2c pin conflicts | ||||
| // | ||||
| #if ANY(HAS_I2C_DIGIPOT, DAC_STEPPER_CURRENT, EXPERIMENTAL_I2CBUS, I2C_POSITION_ENCODERS, PCA9632, I2C_EEPROM) | ||||
| #if ANY(HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC, EXPERIMENTAL_I2CBUS, I2C_POSITION_ENCODERS, PCA9632, I2C_EEPROM) | ||||
|   #define USEDI2CDEV_M 1  // <Arduino>/Wire.cpp | ||||
|  | ||||
|   #if USEDI2CDEV_M == 0         // P0_27 [D57] (AUX-1) .......... P0_28 [D58] (AUX-1) | ||||
|   | ||||
| @@ -97,7 +97,7 @@ | ||||
|   #include "feature/closedloop.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_I2C_DIGIPOT | ||||
| #if HAS_MOTOR_CURRENT_I2C | ||||
|   #include "feature/digipot/digipot.h" | ||||
| #endif | ||||
|  | ||||
| @@ -125,7 +125,7 @@ | ||||
|   #include "module/servo.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(DAC_STEPPER_CURRENT) | ||||
| #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|   #include "feature/dac/stepper_dac.h" | ||||
| #endif | ||||
|  | ||||
| @@ -1137,12 +1137,12 @@ void setup() { | ||||
|     SETUP_RUN(enableStepperDrivers()); | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_I2C_DIGIPOT | ||||
|     SETUP_RUN(digipot_i2c_init()); | ||||
|   #if HAS_MOTOR_CURRENT_I2C | ||||
|     SETUP_RUN(digipot_i2c.init()); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(DAC_STEPPER_CURRENT) | ||||
|     SETUP_RUN(dac_init()); | ||||
|   #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|     SETUP_RUN(stepper_dac.init()); | ||||
|   #endif | ||||
|  | ||||
|   #if EITHER(Z_PROBE_SLED, SOLENOID_PROBE) && HAS_SOLENOID_1 | ||||
|   | ||||
| @@ -32,16 +32,18 @@ | ||||
|  | ||||
| #include "../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if ENABLED(DAC_STEPPER_CURRENT) | ||||
| #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|  | ||||
| #include "dac_mcp4728.h" | ||||
|  | ||||
| xyze_uint_t mcp4728_values; | ||||
| MCP4728 mcp4728; | ||||
|  | ||||
| xyze_uint_t dac_values; | ||||
|  | ||||
| /** | ||||
|  * Begin I2C, get current values (input register and eeprom) of mcp4728 | ||||
|  */ | ||||
| void mcp4728_init() { | ||||
| void MCP4728::init() { | ||||
|   Wire.begin(); | ||||
|   Wire.requestFrom(I2C_ADDRESS(DAC_DEV_ADDRESS), uint8_t(24)); | ||||
|   while (Wire.available()) { | ||||
| @@ -50,7 +52,7 @@ void mcp4728_init() { | ||||
|          loByte = Wire.read(); | ||||
|  | ||||
|     if (!(deviceID & 0x08)) | ||||
|       mcp4728_values[(deviceID & 0x30) >> 4] = word((hiByte & 0x0F), loByte); | ||||
|       dac_values[(deviceID & 0x30) >> 4] = word((hiByte & 0x0F), loByte); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -58,9 +60,9 @@ void mcp4728_init() { | ||||
|  * Write input resister value to specified channel using fastwrite method. | ||||
|  * Channel : 0-3, Values : 0-4095 | ||||
|  */ | ||||
| uint8_t mcp4728_analogWrite(const uint8_t channel, const uint16_t value) { | ||||
|   mcp4728_values[channel] = value; | ||||
|   return mcp4728_fastWrite(); | ||||
| uint8_t MCP4728::analogWrite(const uint8_t channel, const uint16_t value) { | ||||
|   dac_values[channel] = value; | ||||
|   return fastWrite(); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -68,12 +70,12 @@ uint8_t mcp4728_analogWrite(const uint8_t channel, const uint16_t value) { | ||||
|  * This will update both input register and EEPROM value | ||||
|  * This will also write current Vref, PowerDown, Gain settings to EEPROM | ||||
|  */ | ||||
| uint8_t mcp4728_eepromWrite() { | ||||
| uint8_t MCP4728::eepromWrite() { | ||||
|   Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); | ||||
|   Wire.write(SEQWRITE); | ||||
|   LOOP_XYZE(i) { | ||||
|     Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(mcp4728_values[i])); | ||||
|     Wire.write(lowByte(mcp4728_values[i])); | ||||
|     Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(dac_values[i])); | ||||
|     Wire.write(lowByte(dac_values[i])); | ||||
|   } | ||||
|   return Wire.endTransmission(); | ||||
| } | ||||
| @@ -81,7 +83,7 @@ uint8_t mcp4728_eepromWrite() { | ||||
| /** | ||||
|  * Write Voltage reference setting to all input regiters | ||||
|  */ | ||||
| uint8_t mcp4728_setVref_all(const uint8_t value) { | ||||
| uint8_t MCP4728::setVref_all(const uint8_t value) { | ||||
|   Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); | ||||
|   Wire.write(VREFWRITE | (value ? 0x0F : 0x00)); | ||||
|   return Wire.endTransmission(); | ||||
| @@ -89,7 +91,7 @@ uint8_t mcp4728_setVref_all(const uint8_t value) { | ||||
| /** | ||||
|  * Write Gain setting to all input regiters | ||||
|  */ | ||||
| uint8_t mcp4728_setGain_all(const uint8_t value) { | ||||
| uint8_t MCP4728::setGain_all(const uint8_t value) { | ||||
|   Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); | ||||
|   Wire.write(GAINWRITE | (value ? 0x0F : 0x00)); | ||||
|   return Wire.endTransmission(); | ||||
| @@ -98,16 +100,16 @@ uint8_t mcp4728_setGain_all(const uint8_t value) { | ||||
| /** | ||||
|  * Return Input Register value | ||||
|  */ | ||||
| uint16_t mcp4728_getValue(const uint8_t channel) { return mcp4728_values[channel]; } | ||||
| uint16_t MCP4728::getValue(const uint8_t channel) { return dac_values[channel]; } | ||||
|  | ||||
| #if 0 | ||||
| /** | ||||
|  * Steph: Might be useful in the future | ||||
|  * Return Vout | ||||
|  */ | ||||
| uint16_t mcp4728_getVout(const uint8_t channel) { | ||||
| uint16_t MCP4728::getVout(const uint8_t channel) { | ||||
|   const uint32_t vref = 2048, | ||||
|                  vOut = (vref * mcp4728_values[channel] * (_DAC_STEPPER_GAIN + 1)) / 4096; | ||||
|                  vOut = (vref * dac_values[channel] * (_DAC_STEPPER_GAIN + 1)) / 4096; | ||||
|   return _MIN(vOut, defaultVDD); | ||||
| } | ||||
| #endif | ||||
| @@ -115,15 +117,15 @@ uint16_t mcp4728_getVout(const uint8_t channel) { | ||||
| /** | ||||
|  * Returns DAC values as a 0-100 percentage of drive strength | ||||
|  */ | ||||
| uint8_t mcp4728_getDrvPct(const uint8_t channel) { return uint8_t(100.0 * mcp4728_values[channel] / (DAC_STEPPER_MAX) + 0.5); } | ||||
| uint8_t MCP4728::getDrvPct(const uint8_t channel) { return uint8_t(100.0 * dac_values[channel] / (DAC_STEPPER_MAX) + 0.5); } | ||||
|  | ||||
| /** | ||||
|  * Receives all Drive strengths as 0-100 percent values, updates | ||||
|  * DAC Values array and calls fastwrite to update the DAC. | ||||
|  */ | ||||
| void mcp4728_setDrvPct(xyze_uint8_t &pct) { | ||||
|   mcp4728_values *= 0.01 * pct * (DAC_STEPPER_MAX); | ||||
|   mcp4728_fastWrite(); | ||||
| void MCP4728::setDrvPct(xyze_uint8_t &pct) { | ||||
|   dac_values *= 0.01 * pct * (DAC_STEPPER_MAX); | ||||
|   fastWrite(); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -131,11 +133,11 @@ void mcp4728_setDrvPct(xyze_uint8_t &pct) { | ||||
|  * DAC Input and PowerDown bits update. | ||||
|  * No EEPROM update | ||||
|  */ | ||||
| uint8_t mcp4728_fastWrite() { | ||||
| uint8_t MCP4728::fastWrite() { | ||||
|   Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); | ||||
|   LOOP_XYZE(i) { | ||||
|     Wire.write(highByte(mcp4728_values[i])); | ||||
|     Wire.write(lowByte(mcp4728_values[i])); | ||||
|     Wire.write(highByte(dac_values[i])); | ||||
|     Wire.write(lowByte(dac_values[i])); | ||||
|   } | ||||
|   return Wire.endTransmission(); | ||||
| } | ||||
| @@ -143,10 +145,10 @@ uint8_t mcp4728_fastWrite() { | ||||
| /** | ||||
|  * Common function for simple general commands | ||||
|  */ | ||||
| uint8_t mcp4728_simpleCommand(const byte simpleCommand) { | ||||
| uint8_t MCP4728::simpleCommand(const byte simpleCommand) { | ||||
|   Wire.beginTransmission(I2C_ADDRESS(GENERALCALL)); | ||||
|   Wire.write(simpleCommand); | ||||
|   return Wire.endTransmission(); | ||||
| } | ||||
|  | ||||
| #endif // DAC_STEPPER_CURRENT | ||||
| #endif // HAS_MOTOR_CURRENT_DAC | ||||
|   | ||||
| @@ -65,13 +65,18 @@ | ||||
| // DAC_OR_ADDRESS defined in pins_BOARD.h  file | ||||
| #define DAC_DEV_ADDRESS (BASE_ADDR | DAC_OR_ADDRESS) | ||||
|  | ||||
| void mcp4728_init(); | ||||
| uint8_t mcp4728_analogWrite(const uint8_t channel, const uint16_t value); | ||||
| uint8_t mcp4728_eepromWrite(); | ||||
| uint8_t mcp4728_setVref_all(const uint8_t value); | ||||
| uint8_t mcp4728_setGain_all(const uint8_t value); | ||||
| uint16_t mcp4728_getValue(const uint8_t channel); | ||||
| uint8_t mcp4728_fastWrite(); | ||||
| uint8_t mcp4728_simpleCommand(const byte simpleCommand); | ||||
| uint8_t mcp4728_getDrvPct(const uint8_t channel); | ||||
| void mcp4728_setDrvPct(xyze_uint8_t &pct); | ||||
| class MCP4728 { | ||||
| public: | ||||
|   static void     init(); | ||||
|   static uint8_t  analogWrite(const uint8_t channel, const uint16_t value); | ||||
|   static uint8_t  eepromWrite(); | ||||
|   static uint8_t  setVref_all(const uint8_t value); | ||||
|   static uint8_t  setGain_all(const uint8_t value); | ||||
|   static uint16_t getValue(const uint8_t channel); | ||||
|   static uint8_t  fastWrite(); | ||||
|   static uint8_t  simpleCommand(const byte simpleCommand); | ||||
|   static uint8_t  getDrvPct(const uint8_t channel); | ||||
|   static void     setDrvPct(xyze_uint8_t &pct); | ||||
| }; | ||||
|  | ||||
| extern MCP4728 mcp4728; | ||||
|   | ||||
| @@ -26,7 +26,7 @@ | ||||
|  | ||||
| #include "../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if ENABLED(DAC_STEPPER_CURRENT) | ||||
| #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|  | ||||
| #include "stepper_dac.h" | ||||
| #include "../../MarlinCore.h" // for SP_X_LBL... | ||||
| @@ -35,56 +35,53 @@ bool dac_present = false; | ||||
| constexpr xyze_uint8_t dac_order = DAC_STEPPER_ORDER; | ||||
| xyze_uint8_t dac_channel_pct = DAC_MOTOR_CURRENT_DEFAULT; | ||||
|  | ||||
| int dac_init() { | ||||
| StepperDAC stepper_dac; | ||||
|  | ||||
| int StepperDAC::init() { | ||||
|   #if PIN_EXISTS(DAC_DISABLE) | ||||
|     OUT_WRITE(DAC_DISABLE_PIN, LOW);  // set pin low to enable DAC | ||||
|   #endif | ||||
|  | ||||
|   mcp4728_init(); | ||||
|   mcp4728.init(); | ||||
|  | ||||
|   if (mcp4728_simpleCommand(RESET)) return -1; | ||||
|   if (mcp4728.simpleCommand(RESET)) return -1; | ||||
|  | ||||
|   dac_present = true; | ||||
|  | ||||
|   mcp4728_setVref_all(DAC_STEPPER_VREF); | ||||
|   mcp4728_setGain_all(DAC_STEPPER_GAIN); | ||||
|   mcp4728.setVref_all(DAC_STEPPER_VREF); | ||||
|   mcp4728.setGain_all(DAC_STEPPER_GAIN); | ||||
|  | ||||
|   if (mcp4728_getDrvPct(0) < 1 || mcp4728_getDrvPct(1) < 1 || mcp4728_getDrvPct(2) < 1 || mcp4728_getDrvPct(3) < 1 ) { | ||||
|     mcp4728_setDrvPct(dac_channel_pct); | ||||
|     mcp4728_eepromWrite(); | ||||
|   if (mcp4728.getDrvPct(0) < 1 || mcp4728.getDrvPct(1) < 1 || mcp4728.getDrvPct(2) < 1 || mcp4728.getDrvPct(3) < 1 ) { | ||||
|     mcp4728.setDrvPct(dac_channel_pct); | ||||
|     mcp4728.eepromWrite(); | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void dac_current_percent(uint8_t channel, float val) { | ||||
|   if (!dac_present) return; | ||||
|  | ||||
|   NOMORE(val, 100); | ||||
|  | ||||
|   mcp4728_analogWrite(dac_order[channel], val * 0.01 * (DAC_STEPPER_MAX)); | ||||
|   mcp4728_simpleCommand(UPDATE); | ||||
| } | ||||
|  | ||||
| void dac_current_raw(uint8_t channel, uint16_t val) { | ||||
| void StepperDAC::set_current_value(const uint8_t channel, uint16_t val) { | ||||
|   if (!dac_present) return; | ||||
|  | ||||
|   NOMORE(val, uint16_t(DAC_STEPPER_MAX)); | ||||
|  | ||||
|   mcp4728_analogWrite(dac_order[channel], val); | ||||
|   mcp4728_simpleCommand(UPDATE); | ||||
|   mcp4728.analogWrite(dac_order[channel], val); | ||||
|   mcp4728.simpleCommand(UPDATE); | ||||
| } | ||||
|  | ||||
| static float dac_perc(int8_t n) { return 100.0 * mcp4728_getValue(dac_order[n]) * RECIPROCAL(DAC_STEPPER_MAX); } | ||||
| static float dac_amps(int8_t n) { return mcp4728_getDrvPct(dac_order[n]) * (DAC_STEPPER_MAX) * 0.125 * RECIPROCAL(DAC_STEPPER_SENSE); } | ||||
| void StepperDAC::set_current_percent(const uint8_t channel, float val) { | ||||
|   set_current_value(channel, _MIN(val, 100.0f) * (DAC_STEPPER_MAX) / 100.0f); | ||||
| } | ||||
|  | ||||
| uint8_t dac_current_get_percent(const AxisEnum axis) { return mcp4728_getDrvPct(dac_order[axis]); } | ||||
| void dac_current_set_percents(xyze_uint8_t &pct) { | ||||
| static float dac_perc(int8_t n) { return 100.0 * mcp4728.getValue(dac_order[n]) * RECIPROCAL(DAC_STEPPER_MAX); } | ||||
| static float dac_amps(int8_t n) { return mcp4728.getDrvPct(dac_order[n]) * (DAC_STEPPER_MAX) * 0.125 * RECIPROCAL(DAC_STEPPER_SENSE); } | ||||
|  | ||||
| uint8_t StepperDAC::get_current_percent(const AxisEnum axis) { return mcp4728.getDrvPct(dac_order[axis]); } | ||||
| void StepperDAC::set_current_percents(xyze_uint8_t &pct) { | ||||
|   LOOP_XYZE(i) dac_channel_pct[i] = pct[dac_order[i]]; | ||||
|   mcp4728_setDrvPct(dac_channel_pct); | ||||
|   mcp4728.setDrvPct(dac_channel_pct); | ||||
| } | ||||
|  | ||||
| void dac_print_values() { | ||||
| void StepperDAC::print_values() { | ||||
|   if (!dac_present) return; | ||||
|   SERIAL_ECHO_MSG("Stepper current values in % (Amps):"); | ||||
|   SERIAL_ECHO_START(); | ||||
| @@ -94,9 +91,9 @@ void dac_print_values() { | ||||
|   SERIAL_ECHOLNPAIR_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")")); | ||||
| } | ||||
|  | ||||
| void dac_commit_eeprom() { | ||||
| void StepperDAC::commit_eeprom() { | ||||
|   if (!dac_present) return; | ||||
|   mcp4728_eepromWrite(); | ||||
|   mcp4728.eepromWrite(); | ||||
| } | ||||
|  | ||||
| #endif // DAC_STEPPER_CURRENT | ||||
| #endif // HAS_MOTOR_CURRENT_DAC | ||||
|   | ||||
| @@ -27,10 +27,15 @@ | ||||
|  | ||||
| #include "dac_mcp4728.h" | ||||
|  | ||||
| int dac_init(); | ||||
| void dac_current_percent(uint8_t channel, float val); | ||||
| void dac_current_raw(uint8_t channel, uint16_t val); | ||||
| void dac_print_values(); | ||||
| void dac_commit_eeprom(); | ||||
| uint8_t dac_current_get_percent(AxisEnum axis); | ||||
| void dac_current_set_percents(xyze_uint8_t &pct); | ||||
| class StepperDAC { | ||||
| public: | ||||
|   static int init(); | ||||
|   static void set_current_percent(const uint8_t channel, float val); | ||||
|   static void set_current_value(const uint8_t channel, uint16_t val); | ||||
|   static void print_values(); | ||||
|   static void commit_eeprom(); | ||||
|   static uint8_t get_current_percent(AxisEnum axis); | ||||
|   static void set_current_percents(xyze_uint8_t &pct); | ||||
| }; | ||||
|  | ||||
| extern StepperDAC stepper_dac; | ||||
|   | ||||
| @@ -21,5 +21,13 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| void digipot_i2c_set_current(const uint8_t channel, const float current); | ||||
| void digipot_i2c_init(); | ||||
| // | ||||
| // Header for MCP4018 and MCP4451 current control i2c devices | ||||
| // | ||||
| class DigipotI2C { | ||||
| public: | ||||
|   static void init(); | ||||
|   static void set_current(const uint8_t channel, const float current); | ||||
| }; | ||||
|  | ||||
| DigipotI2C digipot_i2c; | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
|  | ||||
| #if ENABLED(DIGIPOT_MCP4018) | ||||
|  | ||||
| #include "digipot.h" | ||||
|  | ||||
| #include <Stream.h> | ||||
| #include <SlowSoftI2CMaster.h>  // https://github.com/stawel/SlowSoftI2CMaster | ||||
|  | ||||
| @@ -68,7 +70,7 @@ static SlowSoftI2CMaster pots[DIGIPOT_I2C_NUM_CHANNELS] = { | ||||
|   #endif | ||||
| }; | ||||
|  | ||||
| static void i2c_send(const uint8_t channel, const byte v) { | ||||
| static void digipot_i2c_send(const uint8_t channel, const byte v) { | ||||
|   if (WITHIN(channel, 0, DIGIPOT_I2C_NUM_CHANNELS - 1)) { | ||||
|     pots[channel].i2c_start(((DIGIPOT_I2C_ADDRESS_A) << 1) | I2C_WRITE); | ||||
|     pots[channel].i2c_write(v); | ||||
| @@ -77,12 +79,12 @@ static void i2c_send(const uint8_t channel, const byte v) { | ||||
| } | ||||
|  | ||||
| // This is for the MCP4018 I2C based digipot | ||||
| void digipot_i2c_set_current(const uint8_t channel, const float current) { | ||||
| void DigipotI2C::set_current(const uint8_t channel, const float current) { | ||||
|   const float ival = _MIN(_MAX(current, 0), float(DIGIPOT_MCP4018_MAX_VALUE)); | ||||
|   i2c_send(channel, current_to_wiper(ival)); | ||||
|   digipot_i2c_send(channel, current_to_wiper(ival)); | ||||
| } | ||||
|  | ||||
| void digipot_i2c_init() { | ||||
| void DigipotI2C::init() { | ||||
|   LOOP_L_N(i, DIGIPOT_I2C_NUM_CHANNELS) pots[i].i2c_init(); | ||||
|  | ||||
|   // Init currents according to Configuration_adv.h | ||||
| @@ -94,7 +96,7 @@ void digipot_i2c_init() { | ||||
|     #endif | ||||
|   ; | ||||
|   LOOP_L_N(i, COUNT(digipot_motor_current)) | ||||
|     digipot_i2c_set_current(i, pgm_read_float(&digipot_motor_current[i])); | ||||
|     set_current(i, pgm_read_float(&digipot_motor_current[i])); | ||||
| } | ||||
|  | ||||
| #endif // DIGIPOT_MCP4018 | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
|  | ||||
| #if ENABLED(DIGIPOT_MCP4451) | ||||
|  | ||||
| #include "digipot.h" | ||||
|  | ||||
| #include <Stream.h> | ||||
| #include <Wire.h> | ||||
|  | ||||
| @@ -61,7 +63,7 @@ static void digipot_i2c_send(const byte addr, const byte a, const byte b) { | ||||
| } | ||||
|  | ||||
| // This is for the MCP4451 I2C based digipot | ||||
| void digipot_i2c_set_current(const uint8_t channel, const float current) { | ||||
| void DigipotI2C::set_current(const uint8_t channel, const float current) { | ||||
|   // These addresses are specific to Azteeg X3 Pro, can be set to others. | ||||
|   // In this case first digipot is at address A0=0, A1=0, second one is at A0=0, A1=1 | ||||
|   const byte addr = channel < 4 ? DIGIPOT_I2C_ADDRESS_A : DIGIPOT_I2C_ADDRESS_B; // channel 0-3 vs 4-7 | ||||
| @@ -75,7 +77,7 @@ void digipot_i2c_set_current(const uint8_t channel, const float current) { | ||||
|   digipot_i2c_send(addr, addresses[channel & 0x3], current_to_wiper(_MIN(float(_MAX(current, 0)), DIGIPOT_I2C_MAX_CURRENT))); | ||||
| } | ||||
|  | ||||
| void digipot_i2c_init() { | ||||
| void DigipotI2C::init() { | ||||
|   #if MB(MKS_SBASE) | ||||
|     configure_i2c(16); // Set clock_option to 16 ensure I2C is initialized at 400kHz | ||||
|   #else | ||||
| @@ -90,7 +92,7 @@ void digipot_i2c_init() { | ||||
|     #endif | ||||
|   ; | ||||
|   LOOP_L_N(i, COUNT(digipot_motor_current)) | ||||
|     digipot_i2c_set_current(i, pgm_read_float(&digipot_motor_current[i])); | ||||
|     set_current(i, pgm_read_float(&digipot_motor_current[i])); | ||||
| } | ||||
|  | ||||
| #endif // DIGIPOT_MCP4451 | ||||
|   | ||||
| @@ -22,19 +22,19 @@ | ||||
|  | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if ANY(HAS_DIGIPOTSS, HAS_MOTOR_CURRENT_PWM, HAS_I2C_DIGIPOT, DAC_STEPPER_CURRENT) | ||||
| #if ANY(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_PWM, HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC) | ||||
|  | ||||
| #include "../../gcode.h" | ||||
|  | ||||
| #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM | ||||
| #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|   #include "../../../module/stepper.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_I2C_DIGIPOT | ||||
| #if HAS_MOTOR_CURRENT_I2C | ||||
|   #include "../../../feature/digipot/digipot.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(DAC_STEPPER_CURRENT) | ||||
| #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|   #include "../../../feature/dac/stepper_dac.h" | ||||
| #endif | ||||
|  | ||||
| @@ -42,61 +42,61 @@ | ||||
|  * M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S | ||||
|  */ | ||||
| void GcodeSuite::M907() { | ||||
|   #if HAS_DIGIPOTSS | ||||
|   #if HAS_MOTOR_CURRENT_SPI | ||||
|  | ||||
|     LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.digipot_current(i, parser.value_int()); | ||||
|     if (parser.seenval('B')) stepper.digipot_current(4, parser.value_int()); | ||||
|     if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.digipot_current(i, parser.value_int()); | ||||
|     LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int()); | ||||
|     if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int()); | ||||
|     if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int()); | ||||
|  | ||||
|   #elif HAS_MOTOR_CURRENT_PWM | ||||
|  | ||||
|     #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) | ||||
|       if (parser.seenval('X') || parser.seenval('Y')) stepper.digipot_current(0, parser.value_int()); | ||||
|       if (parser.seenval('X') || parser.seenval('Y')) stepper.set_digipot_current(0, parser.value_int()); | ||||
|     #endif | ||||
|     #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) | ||||
|       if (parser.seenval('Z')) stepper.digipot_current(1, parser.value_int()); | ||||
|       if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int()); | ||||
|     #endif | ||||
|     #if PIN_EXISTS(MOTOR_CURRENT_PWM_E) | ||||
|       if (parser.seenval('E')) stepper.digipot_current(2, parser.value_int()); | ||||
|       if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int()); | ||||
|     #endif | ||||
|  | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_I2C_DIGIPOT | ||||
|   #if HAS_MOTOR_CURRENT_I2C | ||||
|     // this one uses actual amps in floating point | ||||
|     LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) digipot_i2c_set_current(i, parser.value_float()); | ||||
|     LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) digipot_i2c.set_current(i, parser.value_float()); | ||||
|     // Additional extruders use B,C,D for channels 4,5,6. | ||||
|     // TODO: Change these parameters because 'E' is used. B<index>? | ||||
|     for (uint8_t i = E_AXIS + 1; i < DIGIPOT_I2C_NUM_CHANNELS; i++) | ||||
|       if (parser.seenval('B' + i - (E_AXIS + 1))) digipot_i2c_set_current(i, parser.value_float()); | ||||
|       if (parser.seenval('B' + i - (E_AXIS + 1))) digipot_i2c.set_current(i, parser.value_float()); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(DAC_STEPPER_CURRENT) | ||||
|   #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|     if (parser.seenval('S')) { | ||||
|       const float dac_percent = parser.value_float(); | ||||
|       LOOP_LE_N(i, 4) dac_current_percent(i, dac_percent); | ||||
|       LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent); | ||||
|     } | ||||
|     LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) dac_current_percent(i, parser.value_float()); | ||||
|     LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper_dac.set_current_percent(i, parser.value_float()); | ||||
|   #endif | ||||
| } | ||||
|  | ||||
| #if EITHER(HAS_DIGIPOTSS, DAC_STEPPER_CURRENT) | ||||
| #if EITHER(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_DAC) | ||||
|  | ||||
|   /** | ||||
|    * M908: Control digital trimpot directly (M908 P<pin> S<current>) | ||||
|    */ | ||||
|   void GcodeSuite::M908() { | ||||
|     TERN_(HAS_DIGIPOTSS, stepper.digitalPotWrite(parser.intval('P'), parser.intval('S'))); | ||||
|     TERN_(DAC_STEPPER_CURRENT, dac_current_raw(parser.byteval('P', -1), parser.ushortval('S', 0))); | ||||
|     TERN_(HAS_MOTOR_CURRENT_SPI, stepper.set_digipot_value_spi(parser.intval('P'), parser.intval('S'))); | ||||
|     TERN_(HAS_MOTOR_CURRENT_DAC, stepper_dac.set_current_value(parser.byteval('P', -1), parser.ushortval('S', 0))); | ||||
|   } | ||||
|  | ||||
| #endif // HAS_DIGIPOTSS || DAC_STEPPER_CURRENT | ||||
|   #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|  | ||||
| #if ENABLED(DAC_STEPPER_CURRENT) | ||||
|     void GcodeSuite::M909() { stepper_dac.print_values(); } | ||||
|     void GcodeSuite::M910() { stepper_dac.commit_eeprom(); } | ||||
|  | ||||
|   void GcodeSuite::M909() { dac_print_values(); } | ||||
|   void GcodeSuite::M910() { dac_commit_eeprom(); } | ||||
|   #endif // HAS_MOTOR_CURRENT_DAC | ||||
|  | ||||
| #endif // DAC_STEPPER_CURRENT | ||||
| #endif // HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_DAC | ||||
|  | ||||
| #endif // HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM || HAS_I2C_DIGIPOT || DAC_STEPPER_CURRENT | ||||
| #endif // HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM || HAS_MOTOR_CURRENT_I2C || HAS_MOTOR_CURRENT_DAC | ||||
|   | ||||
| @@ -823,11 +823,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         case 900: M900(); break;                                  // M900: Set advance K factor. | ||||
|       #endif | ||||
|  | ||||
|       #if ANY(HAS_DIGIPOTSS, HAS_MOTOR_CURRENT_PWM, HAS_I2C_DIGIPOT, DAC_STEPPER_CURRENT) | ||||
|       #if ANY(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_PWM, HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC) | ||||
|         case 907: M907(); break;                                  // M907: Set digital trimpot motor current using axis codes. | ||||
|         #if EITHER(HAS_DIGIPOTSS, DAC_STEPPER_CURRENT) | ||||
|         #if EITHER(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_DAC) | ||||
|           case 908: M908(); break;                                // M908: Control digital trimpot directly. | ||||
|           #if ENABLED(DAC_STEPPER_CURRENT) | ||||
|           #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|             case 909: M909(); break;                              // M909: Print digipot/DAC current value | ||||
|             case 910: M910(); break;                              // M910: Commit digipot/DAC value to external EEPROM | ||||
|           #endif | ||||
|   | ||||
| @@ -258,9 +258,9 @@ | ||||
|  * M900 - Get or Set Linear Advance K-factor. (Requires LIN_ADVANCE) | ||||
|  * M906 - Set or get motor current in milliamps using axis codes X, Y, Z, E. Report values if no axis codes given. (Requires at least one _DRIVER_TYPE defined as TMC2130/2160/5130/5160/2208/2209/2660 or L6470) | ||||
|  * M907 - Set digital trimpot motor current using axis codes. (Requires a board with digital trimpots) | ||||
|  * M908 - Control digital trimpot directly. (Requires DAC_STEPPER_CURRENT or DIGIPOTSS_PIN) | ||||
|  * M909 - Print digipot/DAC current value. (Requires DAC_STEPPER_CURRENT) | ||||
|  * M910 - Commit digipot/DAC value to external EEPROM via I2C. (Requires DAC_STEPPER_CURRENT) | ||||
|  * M908 - Control digital trimpot directly. (Requires HAS_MOTOR_CURRENT_DAC or DIGIPOTSS_PIN) | ||||
|  * M909 - Print digipot/DAC current value. (Requires HAS_MOTOR_CURRENT_DAC) | ||||
|  * M910 - Commit digipot/DAC value to external EEPROM via I2C. (Requires HAS_MOTOR_CURRENT_DAC) | ||||
|  * M911 - Report stepper driver overtemperature pre-warn condition. (Requires at least one _DRIVER_TYPE defined as TMC2130/2160/5130/5160/2208/2209/2660) | ||||
|  * M912 - Clear stepper driver overtemperature pre-warn condition flag. (Requires at least one _DRIVER_TYPE defined as TMC2130/2160/5130/5160/2208/2209/2660) | ||||
|  * M913 - Set HYBRID_THRESHOLD speed. (Requires HYBRID_THRESHOLD) | ||||
| @@ -847,11 +847,11 @@ private: | ||||
|     static void M918(); | ||||
|   #endif | ||||
|  | ||||
|   #if ANY(HAS_DIGIPOTSS, HAS_MOTOR_CURRENT_PWM, HAS_I2C_DIGIPOT, DAC_STEPPER_CURRENT) | ||||
|   #if ANY(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_PWM, HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC) | ||||
|     static void M907(); | ||||
|     #if EITHER(HAS_DIGIPOTSS, DAC_STEPPER_CURRENT) | ||||
|     #if EITHER(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_DAC) | ||||
|       static void M908(); | ||||
|       #if ENABLED(DAC_STEPPER_CURRENT) | ||||
|       #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|         static void M909(); | ||||
|         static void M910(); | ||||
|       #endif | ||||
|   | ||||
| @@ -175,7 +175,7 @@ | ||||
| #endif | ||||
|  | ||||
| #if EITHER(DIGIPOT_MCP4018, DIGIPOT_MCP4451) | ||||
|   #define HAS_I2C_DIGIPOT 1 | ||||
|   #define HAS_MOTOR_CURRENT_I2C 1 | ||||
| #endif | ||||
|  | ||||
| // Multiple Z steppers | ||||
|   | ||||
| @@ -1976,7 +1976,7 @@ | ||||
|   #define HAS_STEPPER_RESET 1 | ||||
| #endif | ||||
| #if PIN_EXISTS(DIGIPOTSS) | ||||
|   #define HAS_DIGIPOTSS 1 | ||||
|   #define HAS_MOTOR_CURRENT_SPI 1 | ||||
| #endif | ||||
| #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_Z, MOTOR_CURRENT_PWM_E) | ||||
|   #define HAS_MOTOR_CURRENT_PWM 1 | ||||
|   | ||||
| @@ -2667,7 +2667,7 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal | ||||
| /** | ||||
|  * Digipot requirement | ||||
|  */ | ||||
| #if HAS_I2C_DIGIPOT | ||||
| #if HAS_MOTOR_CURRENT_I2C | ||||
|   #if BOTH(DIGIPOT_MCP4018, DIGIPOT_MCP4451) | ||||
|     #error "Enable only one of DIGIPOT_MCP4018 or DIGIPOT_MCP4451." | ||||
|   #elif !MB(MKS_SBASE) \ | ||||
|   | ||||
| @@ -58,16 +58,16 @@ | ||||
| void menu_tmc(); | ||||
| void menu_backlash(); | ||||
|  | ||||
| #if ENABLED(DAC_STEPPER_CURRENT) | ||||
| #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|  | ||||
|   #include "../../feature/dac/stepper_dac.h" | ||||
|  | ||||
|   void menu_dac() { | ||||
|     static xyze_uint8_t driverPercent; | ||||
|     LOOP_XYZE(i) driverPercent[i] = dac_current_get_percent((AxisEnum)i); | ||||
|     LOOP_XYZE(i) driverPercent[i] = stepper_dac.get_current_percent((AxisEnum)i); | ||||
|     START_MENU(); | ||||
|     BACK_ITEM(MSG_ADVANCED_SETTINGS); | ||||
|     #define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ dac_current_set_percents(driverPercent); }) | ||||
|     #define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); }) | ||||
|     EDIT_DAC_PERCENT(X); | ||||
|     EDIT_DAC_PERCENT(Y); | ||||
|     EDIT_DAC_PERCENT(Z); | ||||
| @@ -568,7 +568,7 @@ void menu_advanced_settings() { | ||||
|     SUBMENU(MSG_BACKLASH, menu_backlash); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(DAC_STEPPER_CURRENT) | ||||
|   #if ENABLED(HAS_MOTOR_CURRENT_DAC) | ||||
|     SUBMENU(MSG_DRIVE_STRENGTH, menu_dac); | ||||
|   #endif | ||||
|   #if HAS_MOTOR_CURRENT_PWM | ||||
|   | ||||
| @@ -36,7 +36,7 @@ | ||||
|  */ | ||||
|  | ||||
| // Change EEPROM version if the structure changes | ||||
| #define EEPROM_VERSION "V81" | ||||
| #define EEPROM_VERSION "V82" | ||||
| #define EEPROM_OFFSET 100 | ||||
|  | ||||
| // Check the integrity of data offsets. | ||||
| @@ -365,7 +365,10 @@ typedef struct SettingsDataStruct { | ||||
|   // | ||||
|   // HAS_MOTOR_CURRENT_PWM | ||||
|   // | ||||
|   uint32_t motor_current_setting[3];                    // M907 X Z E | ||||
|   #ifndef MOTOR_CURRENT_COUNT | ||||
|     #define MOTOR_CURRENT_COUNT 3 | ||||
|   #endif | ||||
|   uint32_t motor_current_setting[MOTOR_CURRENT_COUNT];  // M907 X Z E | ||||
|  | ||||
|   // | ||||
|   // CNC_COORDINATE_SYSTEMS | ||||
| @@ -1277,10 +1280,10 @@ void MarlinSettings::postprocess() { | ||||
|     { | ||||
|       _FIELD_TEST(motor_current_setting); | ||||
|  | ||||
|       #if HAS_MOTOR_CURRENT_PWM | ||||
|       #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|         EEPROM_WRITE(stepper.motor_current_setting); | ||||
|       #else | ||||
|         const uint32_t no_current[3] = { 0 }; | ||||
|         const uint32_t no_current[MOTOR_CURRENT_COUNT] = { 0 }; | ||||
|         EEPROM_WRITE(no_current); | ||||
|       #endif | ||||
|     } | ||||
| @@ -2110,10 +2113,16 @@ void MarlinSettings::postprocess() { | ||||
|       // Motor Current PWM | ||||
|       // | ||||
|       { | ||||
|         uint32_t motor_current_setting[3]; | ||||
|         _FIELD_TEST(motor_current_setting); | ||||
|         uint32_t motor_current_setting[MOTOR_CURRENT_COUNT] | ||||
|           #if HAS_MOTOR_CURRENT_SPI | ||||
|              = DIGIPOT_MOTOR_CURRENT | ||||
|           #endif | ||||
|         ; | ||||
|         DEBUG_ECHOLNPGM("DIGIPOTS Loading"); | ||||
|         EEPROM_READ(motor_current_setting); | ||||
|         #if HAS_MOTOR_CURRENT_PWM | ||||
|         DEBUG_ECHOLNPGM("DIGIPOTS Loaded"); | ||||
|         #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|           if (!validating) | ||||
|             COPY(stepper.motor_current_setting, motor_current_setting); | ||||
|         #endif | ||||
| @@ -2791,9 +2800,20 @@ void MarlinSettings::reset() { | ||||
|   // | ||||
|  | ||||
|   #if HAS_MOTOR_CURRENT_PWM | ||||
|     constexpr uint32_t tmp_motor_current_setting[3] = PWM_MOTOR_CURRENT; | ||||
|     LOOP_L_N(q, 3) | ||||
|       stepper.digipot_current(q, (stepper.motor_current_setting[q] = tmp_motor_current_setting[q])); | ||||
|     constexpr uint32_t tmp_motor_current_setting[MOTOR_CURRENT_COUNT] = PWM_MOTOR_CURRENT; | ||||
|     LOOP_L_N(q, MOTOR_CURRENT_COUNT) | ||||
|       stepper.set_digipot_current(q, (stepper.motor_current_setting[q] = tmp_motor_current_setting[q])); | ||||
|   #endif | ||||
|  | ||||
|   // | ||||
|   // DIGIPOTS | ||||
|   // | ||||
|   #if HAS_MOTOR_CURRENT_SPI | ||||
|     static constexpr uint32_t tmp_motor_current_setting[] = DIGIPOT_MOTOR_CURRENT; | ||||
|     DEBUG_ECHOLNPGM("Writing Digipot"); | ||||
|     LOOP_L_N(q, COUNT(tmp_motor_current_setting)) | ||||
|       stepper.set_digipot_current(q, tmp_motor_current_setting[q]); | ||||
|     DEBUG_ECHOLNPGM("Digipot Written"); | ||||
|   #endif | ||||
|  | ||||
|   // | ||||
| @@ -3695,14 +3715,23 @@ void MarlinSettings::reset() { | ||||
|       #endif | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_MOTOR_CURRENT_PWM | ||||
|     #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|       CONFIG_ECHO_HEADING("Stepper motor currents:"); | ||||
|       CONFIG_ECHO_START(); | ||||
|       SERIAL_ECHOLNPAIR_P( | ||||
|           PSTR("  M907 X"), stepper.motor_current_setting[0] | ||||
|         , SP_Z_STR, stepper.motor_current_setting[1] | ||||
|         , SP_E_STR, stepper.motor_current_setting[2] | ||||
|       ); | ||||
|       #if HAS_MOTOR_CURRENT_PWM | ||||
|         SERIAL_ECHOLNPAIR_P( | ||||
|             PSTR("  M907 X"), stepper.motor_current_setting[0] | ||||
|           , SP_Z_STR, stepper.motor_current_setting[1] | ||||
|           , SP_E_STR, stepper.motor_current_setting[2] | ||||
|         ); | ||||
|       #elif HAS_MOTOR_CURRENT_SPI | ||||
|         SERIAL_ECHOPGM("  M907"); | ||||
|         LOOP_L_N(q, MOTOR_CURRENT_COUNT) { | ||||
|           SERIAL_CHAR(' '); | ||||
|           SERIAL_CHAR(axis_codes[q]); | ||||
|           SERIAL_ECHO(stepper.motor_current_setting[q]); | ||||
|         } | ||||
|       #endif | ||||
|     #endif | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -83,10 +83,6 @@ Stepper stepper; // Singleton | ||||
|  | ||||
| #define BABYSTEPPING_EXTRA_DIR_WAIT | ||||
|  | ||||
| #if HAS_MOTOR_CURRENT_PWM | ||||
|   bool Stepper::initialized; // = false | ||||
| #endif | ||||
|  | ||||
| #ifdef __AVR__ | ||||
|   #include "speed_lookuptable.h" | ||||
| #endif | ||||
| @@ -110,7 +106,7 @@ Stepper stepper; // Singleton | ||||
|   #include "../feature/dac/dac_dac084s085.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_DIGIPOTSS | ||||
| #if HAS_MOTOR_CURRENT_SPI | ||||
|   #include <SPI.h> | ||||
| #endif | ||||
|  | ||||
| @@ -142,8 +138,12 @@ Stepper stepper; // Singleton | ||||
|   bool Stepper::separate_multi_axis = false; | ||||
| #endif | ||||
|  | ||||
| #if HAS_MOTOR_CURRENT_PWM | ||||
|   uint32_t Stepper::motor_current_setting[3]; // Initialized by settings.load() | ||||
| #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|   bool Stepper::initialized; // = false | ||||
|   uint32_t Stepper::motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load() | ||||
|   #if HAS_MOTOR_CURRENT_SPI | ||||
|     constexpr uint32_t Stepper::digipot_count[]; | ||||
|   #endif | ||||
| #endif | ||||
|  | ||||
| // private: | ||||
| @@ -2590,8 +2590,8 @@ void Stepper::init() { | ||||
|  | ||||
|   set_directions(); | ||||
|  | ||||
|   #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM | ||||
|     TERN_(HAS_MOTOR_CURRENT_PWM, initialized = true); | ||||
|   #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|     initialized = true; | ||||
|     digipot_init(); | ||||
|   #endif | ||||
| } | ||||
| @@ -2930,10 +2930,10 @@ void Stepper::report_positions() { | ||||
|  * Software-controlled Stepper Motor Current | ||||
|  */ | ||||
|  | ||||
| #if HAS_DIGIPOTSS | ||||
| #if HAS_MOTOR_CURRENT_SPI | ||||
|  | ||||
|   // From Arduino DigitalPotControl example | ||||
|   void Stepper::digitalPotWrite(const int16_t address, const int16_t value) { | ||||
|   void Stepper::set_digipot_value_spi(const int16_t address, const int16_t value) { | ||||
|     WRITE(DIGIPOTSS_PIN, LOW);  // Take the SS pin low to select the chip | ||||
|     SPI.transfer(address);      // Send the address and value via SPI | ||||
|     SPI.transfer(value); | ||||
| @@ -2941,7 +2941,7 @@ void Stepper::report_positions() { | ||||
|     //delay(10); | ||||
|   } | ||||
|  | ||||
| #endif // HAS_DIGIPOTSS | ||||
| #endif // HAS_MOTOR_CURRENT_SPI | ||||
|  | ||||
| #if HAS_MOTOR_CURRENT_PWM | ||||
|  | ||||
| @@ -2958,7 +2958,7 @@ void Stepper::report_positions() { | ||||
|         #if ANY_PIN(MOTOR_CURRENT_PWM_E, MOTOR_CURRENT_PWM_E0, MOTOR_CURRENT_PWM_E1) | ||||
|           case 2: | ||||
|         #endif | ||||
|             digipot_current(i, motor_current_setting[i]); | ||||
|             set_digipot_current(i, motor_current_setting[i]); | ||||
|         default: break; | ||||
|       } | ||||
|     } | ||||
| @@ -2968,22 +2968,23 @@ void Stepper::report_positions() { | ||||
|  | ||||
| #if !MB(PRINTRBOARD_G2) | ||||
|  | ||||
|   #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM | ||||
|   #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|  | ||||
|     void Stepper::digipot_current(const uint8_t driver, const int16_t current) { | ||||
|     void Stepper::set_digipot_current(const uint8_t driver, const int16_t current) { | ||||
|       if (WITHIN(driver, 0, COUNT(motor_current_setting) - 1)) | ||||
|         motor_current_setting[driver] = current; // update motor_current_setting | ||||
|  | ||||
|       #if HAS_DIGIPOTSS | ||||
|       if (!initialized) return; | ||||
|  | ||||
|       #if HAS_MOTOR_CURRENT_SPI | ||||
|  | ||||
|         //SERIAL_ECHOLNPAIR("Digipotss current ", current); | ||||
|  | ||||
|         const uint8_t digipot_ch[] = DIGIPOT_CHANNELS; | ||||
|         digitalPotWrite(digipot_ch[driver], current); | ||||
|         set_digipot_value_spi(digipot_ch[driver], current); | ||||
|  | ||||
|       #elif HAS_MOTOR_CURRENT_PWM | ||||
|  | ||||
|         if (!initialized) return; | ||||
|  | ||||
|         if (WITHIN(driver, 0, COUNT(motor_current_setting) - 1)) | ||||
|           motor_current_setting[driver] = current; // update motor_current_setting | ||||
|  | ||||
|         #define _WRITE_CURRENT_PWM(P) analogWrite(pin_t(MOTOR_CURRENT_PWM_## P ##_PIN), 255L * current / (MOTOR_CURRENT_PWM_RANGE)) | ||||
|         switch (driver) { | ||||
|           case 0: | ||||
| @@ -3019,17 +3020,13 @@ void Stepper::report_positions() { | ||||
|  | ||||
|     void Stepper::digipot_init() { | ||||
|  | ||||
|       #if HAS_DIGIPOTSS | ||||
|  | ||||
|         static const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT; | ||||
|       #if HAS_MOTOR_CURRENT_SPI | ||||
|  | ||||
|         SPI.begin(); | ||||
|         SET_OUTPUT(DIGIPOTSS_PIN); | ||||
|  | ||||
|         LOOP_L_N(i, COUNT(digipot_motor_current)) { | ||||
|           //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]); | ||||
|           digipot_current(i, digipot_motor_current[i]); | ||||
|         } | ||||
|         LOOP_L_N(i, COUNT(motor_current_setting)) | ||||
|           set_digipot_current(i, motor_current_setting[i]); | ||||
|  | ||||
|       #elif HAS_MOTOR_CURRENT_PWM | ||||
|  | ||||
|   | ||||
| @@ -245,12 +245,18 @@ class Stepper { | ||||
|       static bool separate_multi_axis; | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_MOTOR_CURRENT_PWM | ||||
|       #ifndef PWM_MOTOR_CURRENT | ||||
|         #define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT | ||||
|     #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|       #if HAS_MOTOR_CURRENT_PWM | ||||
|         #ifndef PWM_MOTOR_CURRENT | ||||
|           #define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT | ||||
|         #endif | ||||
|         #define MOTOR_CURRENT_COUNT 3 | ||||
|       #elif HAS_MOTOR_CURRENT_SPI | ||||
|         static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT; | ||||
|         #define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count) | ||||
|       #endif | ||||
|       static uint32_t motor_current_setting[3]; | ||||
|       static bool initialized; | ||||
|       static uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load() | ||||
|     #endif | ||||
|  | ||||
|     // Last-moved extruder, as set when the last movement was fetched from planner | ||||
| @@ -457,9 +463,9 @@ class Stepper { | ||||
|     // Triggered position of an axis in steps | ||||
|     static int32_t triggered_position(const AxisEnum axis); | ||||
|  | ||||
|     #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM | ||||
|       static void digitalPotWrite(const int16_t address, const int16_t value); | ||||
|       static void digipot_current(const uint8_t driver, const int16_t current); | ||||
|     #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|       static void set_digipot_value_spi(const int16_t address, const int16_t value); | ||||
|       static void set_digipot_current(const uint8_t driver, const int16_t current); | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_MICROSTEPS | ||||
| @@ -582,7 +588,7 @@ class Stepper { | ||||
|       static int32_t _eval_bezier_curve(const uint32_t curr_step); | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM | ||||
|     #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM | ||||
|       static void digipot_init(); | ||||
|     #endif | ||||
|  | ||||
|   | ||||
| @@ -34,7 +34,7 @@ | ||||
| // | ||||
|  | ||||
| // I2C based DAC like on the Printrboard REVF | ||||
| #define DAC_STEPPER_CURRENT | ||||
| #define HAS_MOTOR_CURRENT_DAC | ||||
|  | ||||
| // Channels available for DAC, For Rigidboard there are 4 | ||||
| #define DAC_STEPPER_ORDER { 0, 1, 2, 3 } | ||||
|   | ||||
| @@ -143,7 +143,7 @@ | ||||
| #endif // NO_EXTRUDRBOARD | ||||
|  | ||||
| // Enable control of stepper motor currents with the I2C based MCP4728 DAC used on Printrboard REVF | ||||
| #define DAC_STEPPER_CURRENT | ||||
| #define HAS_MOTOR_CURRENT_DAC | ||||
|  | ||||
| // Set default drive strength percents if not already defined - X, Y, Z, E axis | ||||
| #ifndef DAC_MOTOR_CURRENT_DEFAULT | ||||
|   | ||||
| @@ -211,7 +211,7 @@ HAS_TRINAMIC_CONFIG     = TMCStepper@~0.7.1 | ||||
|                           src_filter=+<src/feature/tmc_util.cpp> +<src/module/stepper/trinamic.cpp> +<src/gcode/feature/trinamic/M122.cpp> +<src/gcode/feature/trinamic/M906.cpp> +<src/gcode/feature/trinamic/M911-M914.cpp> | ||||
| HAS_STEALTHCHOP         = src_filter=+<src/gcode/feature/trinamic/M569.cpp> | ||||
| SR_LCD_3W_NL            = SailfishLCD=https://github.com/mikeshub/SailfishLCD/archive/master.zip | ||||
| HAS_I2C_DIGIPOT         = SlowSoftI2CMaster | ||||
| HAS_MOTOR_CURRENT_I2C   = SlowSoftI2CMaster | ||||
|                           src_filter=+<src/feature/digipot> | ||||
| HAS_TMC26X              = TMC26XStepper=https://github.com/trinamic/TMC26XStepper/archive/master.zip | ||||
|                           src_filter=+<src/module/TMC26X.cpp> | ||||
| @@ -277,7 +277,7 @@ CANCEL_OBJECTS          = src_filter=+<src/feature/cancel_object.cpp> +<src/gcod | ||||
| CASE_LIGHT_ENABLE       = src_filter=+<src/feature/caselight.cpp> +<src/gcode/feature/caselight> | ||||
| EXTERNAL_CLOSED_LOOP_CONTROLLER = src_filter=+<src/feature/closedloop.cpp> +<src/gcode/calibrate/M12.cpp> | ||||
| USE_CONTROLLER_FAN      = src_filter=+<src/feature/controllerfan.cpp> | ||||
| DAC_STEPPER_CURRENT     = src_filter=+<src/feature/dac> | ||||
| HAS_MOTOR_CURRENT_DAC   = src_filter=+<src/feature/dac> | ||||
| DIRECT_STEPPING         = src_filter=+<src/feature/direct_stepping.cpp> +<src/gcode/motion/G6.cpp> | ||||
| EMERGENCY_PARSER        = src_filter=+<src/feature/e_parser.cpp> -<src/gcode/control/M108_*.cpp> | ||||
| I2C_POSITION_ENCODERS   = src_filter=+<src/feature/encoder_i2c.cpp> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user