Digipots refactor / cleanup (#19690)

This commit is contained in:
Scott Lahteine 2020-10-11 14:58:35 -05:00
parent 2e01eb9189
commit a30e8baf3e
23 changed files with 240 additions and 187 deletions

View file

@ -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) 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 if (!(PWM->PWM_CH_NUM[0].PWM_CPRD == PWM_PERIOD_US)) digipot_init(); // Init PWM system if needed

View file

@ -191,7 +191,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
// //
// Flag any i2c pin conflicts // 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 #define USEDI2CDEV_M 1 // <Arduino>/Wire.cpp
#if USEDI2CDEV_M == 0 // P0_27 [D57] (AUX-1) .......... P0_28 [D58] (AUX-1) #if USEDI2CDEV_M == 0 // P0_27 [D57] (AUX-1) .......... P0_28 [D58] (AUX-1)

View file

@ -97,7 +97,7 @@
#include "feature/closedloop.h" #include "feature/closedloop.h"
#endif #endif
#if HAS_I2C_DIGIPOT #if HAS_MOTOR_CURRENT_I2C
#include "feature/digipot/digipot.h" #include "feature/digipot/digipot.h"
#endif #endif
@ -125,7 +125,7 @@
#include "module/servo.h" #include "module/servo.h"
#endif #endif
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
#include "feature/dac/stepper_dac.h" #include "feature/dac/stepper_dac.h"
#endif #endif
@ -1137,12 +1137,12 @@ void setup() {
SETUP_RUN(enableStepperDrivers()); SETUP_RUN(enableStepperDrivers());
#endif #endif
#if HAS_I2C_DIGIPOT #if HAS_MOTOR_CURRENT_I2C
SETUP_RUN(digipot_i2c_init()); SETUP_RUN(digipot_i2c.init());
#endif #endif
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
SETUP_RUN(dac_init()); SETUP_RUN(stepper_dac.init());
#endif #endif
#if EITHER(Z_PROBE_SLED, SOLENOID_PROBE) && HAS_SOLENOID_1 #if EITHER(Z_PROBE_SLED, SOLENOID_PROBE) && HAS_SOLENOID_1

View file

@ -32,16 +32,18 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
#include "dac_mcp4728.h" #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 * Begin I2C, get current values (input register and eeprom) of mcp4728
*/ */
void mcp4728_init() { void MCP4728::init() {
Wire.begin(); Wire.begin();
Wire.requestFrom(I2C_ADDRESS(DAC_DEV_ADDRESS), uint8_t(24)); Wire.requestFrom(I2C_ADDRESS(DAC_DEV_ADDRESS), uint8_t(24));
while (Wire.available()) { while (Wire.available()) {
@ -50,7 +52,7 @@ void mcp4728_init() {
loByte = Wire.read(); loByte = Wire.read();
if (!(deviceID & 0x08)) 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. * Write input resister value to specified channel using fastwrite method.
* Channel : 0-3, Values : 0-4095 * Channel : 0-3, Values : 0-4095
*/ */
uint8_t mcp4728_analogWrite(const uint8_t channel, const uint16_t value) { uint8_t MCP4728::analogWrite(const uint8_t channel, const uint16_t value) {
mcp4728_values[channel] = value; dac_values[channel] = value;
return mcp4728_fastWrite(); 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 update both input register and EEPROM value
* This will also write current Vref, PowerDown, Gain settings to EEPROM * 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.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
Wire.write(SEQWRITE); Wire.write(SEQWRITE);
LOOP_XYZE(i) { LOOP_XYZE(i) {
Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(mcp4728_values[i])); Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(dac_values[i]));
Wire.write(lowByte(mcp4728_values[i])); Wire.write(lowByte(dac_values[i]));
} }
return Wire.endTransmission(); return Wire.endTransmission();
} }
@ -81,7 +83,7 @@ uint8_t mcp4728_eepromWrite() {
/** /**
* Write Voltage reference setting to all input regiters * 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.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
Wire.write(VREFWRITE | (value ? 0x0F : 0x00)); Wire.write(VREFWRITE | (value ? 0x0F : 0x00));
return Wire.endTransmission(); return Wire.endTransmission();
@ -89,7 +91,7 @@ uint8_t mcp4728_setVref_all(const uint8_t value) {
/** /**
* Write Gain setting to all input regiters * 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.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
Wire.write(GAINWRITE | (value ? 0x0F : 0x00)); Wire.write(GAINWRITE | (value ? 0x0F : 0x00));
return Wire.endTransmission(); return Wire.endTransmission();
@ -98,16 +100,16 @@ uint8_t mcp4728_setGain_all(const uint8_t value) {
/** /**
* Return Input Register 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 #if 0
/** /**
* Steph: Might be useful in the future * Steph: Might be useful in the future
* Return Vout * Return Vout
*/ */
uint16_t mcp4728_getVout(const uint8_t channel) { uint16_t MCP4728::getVout(const uint8_t channel) {
const uint32_t vref = 2048, 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); return _MIN(vOut, defaultVDD);
} }
#endif #endif
@ -115,15 +117,15 @@ uint16_t mcp4728_getVout(const uint8_t channel) {
/** /**
* Returns DAC values as a 0-100 percentage of drive strength * 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 * Receives all Drive strengths as 0-100 percent values, updates
* DAC Values array and calls fastwrite to update the DAC. * DAC Values array and calls fastwrite to update the DAC.
*/ */
void mcp4728_setDrvPct(xyze_uint8_t &pct) { void MCP4728::setDrvPct(xyze_uint8_t &pct) {
mcp4728_values *= 0.01 * pct * (DAC_STEPPER_MAX); dac_values *= 0.01 * pct * (DAC_STEPPER_MAX);
mcp4728_fastWrite(); fastWrite();
} }
/** /**
@ -131,11 +133,11 @@ void mcp4728_setDrvPct(xyze_uint8_t &pct) {
* DAC Input and PowerDown bits update. * DAC Input and PowerDown bits update.
* No EEPROM update * No EEPROM update
*/ */
uint8_t mcp4728_fastWrite() { uint8_t MCP4728::fastWrite() {
Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS)); Wire.beginTransmission(I2C_ADDRESS(DAC_DEV_ADDRESS));
LOOP_XYZE(i) { LOOP_XYZE(i) {
Wire.write(highByte(mcp4728_values[i])); Wire.write(highByte(dac_values[i]));
Wire.write(lowByte(mcp4728_values[i])); Wire.write(lowByte(dac_values[i]));
} }
return Wire.endTransmission(); return Wire.endTransmission();
} }
@ -143,10 +145,10 @@ uint8_t mcp4728_fastWrite() {
/** /**
* Common function for simple general commands * 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.beginTransmission(I2C_ADDRESS(GENERALCALL));
Wire.write(simpleCommand); Wire.write(simpleCommand);
return Wire.endTransmission(); return Wire.endTransmission();
} }
#endif // DAC_STEPPER_CURRENT #endif // HAS_MOTOR_CURRENT_DAC

View file

@ -65,13 +65,18 @@
// DAC_OR_ADDRESS defined in pins_BOARD.h file // DAC_OR_ADDRESS defined in pins_BOARD.h file
#define DAC_DEV_ADDRESS (BASE_ADDR | DAC_OR_ADDRESS) #define DAC_DEV_ADDRESS (BASE_ADDR | DAC_OR_ADDRESS)
void mcp4728_init(); class MCP4728 {
uint8_t mcp4728_analogWrite(const uint8_t channel, const uint16_t value); public:
uint8_t mcp4728_eepromWrite(); static void init();
uint8_t mcp4728_setVref_all(const uint8_t value); static uint8_t analogWrite(const uint8_t channel, const uint16_t value);
uint8_t mcp4728_setGain_all(const uint8_t value); static uint8_t eepromWrite();
uint16_t mcp4728_getValue(const uint8_t channel); static uint8_t setVref_all(const uint8_t value);
uint8_t mcp4728_fastWrite(); static uint8_t setGain_all(const uint8_t value);
uint8_t mcp4728_simpleCommand(const byte simpleCommand); static uint16_t getValue(const uint8_t channel);
uint8_t mcp4728_getDrvPct(const uint8_t channel); static uint8_t fastWrite();
void mcp4728_setDrvPct(xyze_uint8_t &pct); 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;

View file

@ -26,7 +26,7 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
#include "stepper_dac.h" #include "stepper_dac.h"
#include "../../MarlinCore.h" // for SP_X_LBL... #include "../../MarlinCore.h" // for SP_X_LBL...
@ -35,56 +35,53 @@ bool dac_present = false;
constexpr xyze_uint8_t dac_order = DAC_STEPPER_ORDER; constexpr xyze_uint8_t dac_order = DAC_STEPPER_ORDER;
xyze_uint8_t dac_channel_pct = DAC_MOTOR_CURRENT_DEFAULT; xyze_uint8_t dac_channel_pct = DAC_MOTOR_CURRENT_DEFAULT;
int dac_init() { StepperDAC stepper_dac;
int StepperDAC::init() {
#if PIN_EXISTS(DAC_DISABLE) #if PIN_EXISTS(DAC_DISABLE)
OUT_WRITE(DAC_DISABLE_PIN, LOW); // set pin low to enable DAC OUT_WRITE(DAC_DISABLE_PIN, LOW); // set pin low to enable DAC
#endif #endif
mcp4728_init(); mcp4728.init();
if (mcp4728_simpleCommand(RESET)) return -1; if (mcp4728.simpleCommand(RESET)) return -1;
dac_present = true; dac_present = true;
mcp4728_setVref_all(DAC_STEPPER_VREF); mcp4728.setVref_all(DAC_STEPPER_VREF);
mcp4728_setGain_all(DAC_STEPPER_GAIN); mcp4728.setGain_all(DAC_STEPPER_GAIN);
if (mcp4728_getDrvPct(0) < 1 || mcp4728_getDrvPct(1) < 1 || mcp4728_getDrvPct(2) < 1 || mcp4728_getDrvPct(3) < 1 ) { if (mcp4728.getDrvPct(0) < 1 || mcp4728.getDrvPct(1) < 1 || mcp4728.getDrvPct(2) < 1 || mcp4728.getDrvPct(3) < 1 ) {
mcp4728_setDrvPct(dac_channel_pct); mcp4728.setDrvPct(dac_channel_pct);
mcp4728_eepromWrite(); mcp4728.eepromWrite();
} }
return 0; return 0;
} }
void dac_current_percent(uint8_t channel, float val) { void StepperDAC::set_current_value(const uint8_t channel, uint16_t 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) {
if (!dac_present) return; if (!dac_present) return;
NOMORE(val, uint16_t(DAC_STEPPER_MAX)); NOMORE(val, uint16_t(DAC_STEPPER_MAX));
mcp4728_analogWrite(dac_order[channel], val); mcp4728.analogWrite(dac_order[channel], val);
mcp4728_simpleCommand(UPDATE); mcp4728.simpleCommand(UPDATE);
} }
static float dac_perc(int8_t n) { return 100.0 * mcp4728_getValue(dac_order[n]) * RECIPROCAL(DAC_STEPPER_MAX); } void StepperDAC::set_current_percent(const uint8_t channel, float val) {
static float dac_amps(int8_t n) { return mcp4728_getDrvPct(dac_order[n]) * (DAC_STEPPER_MAX) * 0.125 * RECIPROCAL(DAC_STEPPER_SENSE); } 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]); } static float dac_perc(int8_t n) { return 100.0 * mcp4728.getValue(dac_order[n]) * RECIPROCAL(DAC_STEPPER_MAX); }
void dac_current_set_percents(xyze_uint8_t &pct) { 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]]; 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; if (!dac_present) return;
SERIAL_ECHO_MSG("Stepper current values in % (Amps):"); SERIAL_ECHO_MSG("Stepper current values in % (Amps):");
SERIAL_ECHO_START(); 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(")")); 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; if (!dac_present) return;
mcp4728_eepromWrite(); mcp4728.eepromWrite();
} }
#endif // DAC_STEPPER_CURRENT #endif // HAS_MOTOR_CURRENT_DAC

View file

@ -27,10 +27,15 @@
#include "dac_mcp4728.h" #include "dac_mcp4728.h"
int dac_init(); class StepperDAC {
void dac_current_percent(uint8_t channel, float val); public:
void dac_current_raw(uint8_t channel, uint16_t val); static int init();
void dac_print_values(); static void set_current_percent(const uint8_t channel, float val);
void dac_commit_eeprom(); static void set_current_value(const uint8_t channel, uint16_t val);
uint8_t dac_current_get_percent(AxisEnum axis); static void print_values();
void dac_current_set_percents(xyze_uint8_t &pct); 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;

View file

@ -21,5 +21,13 @@
*/ */
#pragma once #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;

View file

@ -24,6 +24,8 @@
#if ENABLED(DIGIPOT_MCP4018) #if ENABLED(DIGIPOT_MCP4018)
#include "digipot.h"
#include <Stream.h> #include <Stream.h>
#include <SlowSoftI2CMaster.h> // https://github.com/stawel/SlowSoftI2CMaster #include <SlowSoftI2CMaster.h> // https://github.com/stawel/SlowSoftI2CMaster
@ -68,7 +70,7 @@ static SlowSoftI2CMaster pots[DIGIPOT_I2C_NUM_CHANNELS] = {
#endif #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)) { if (WITHIN(channel, 0, DIGIPOT_I2C_NUM_CHANNELS - 1)) {
pots[channel].i2c_start(((DIGIPOT_I2C_ADDRESS_A) << 1) | I2C_WRITE); pots[channel].i2c_start(((DIGIPOT_I2C_ADDRESS_A) << 1) | I2C_WRITE);
pots[channel].i2c_write(v); 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 // 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)); 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(); LOOP_L_N(i, DIGIPOT_I2C_NUM_CHANNELS) pots[i].i2c_init();
// Init currents according to Configuration_adv.h // Init currents according to Configuration_adv.h
@ -94,7 +96,7 @@ void digipot_i2c_init() {
#endif #endif
; ;
LOOP_L_N(i, COUNT(digipot_motor_current)) 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 #endif // DIGIPOT_MCP4018

View file

@ -24,6 +24,8 @@
#if ENABLED(DIGIPOT_MCP4451) #if ENABLED(DIGIPOT_MCP4451)
#include "digipot.h"
#include <Stream.h> #include <Stream.h>
#include <Wire.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 // 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. // 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 // 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 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))); 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) #if MB(MKS_SBASE)
configure_i2c(16); // Set clock_option to 16 ensure I2C is initialized at 400kHz configure_i2c(16); // Set clock_option to 16 ensure I2C is initialized at 400kHz
#else #else
@ -90,7 +92,7 @@ void digipot_i2c_init() {
#endif #endif
; ;
LOOP_L_N(i, COUNT(digipot_motor_current)) 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 #endif // DIGIPOT_MCP4451

View file

@ -22,19 +22,19 @@
#include "../../../inc/MarlinConfig.h" #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" #include "../../gcode.h"
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
#include "../../../module/stepper.h" #include "../../../module/stepper.h"
#endif #endif
#if HAS_I2C_DIGIPOT #if HAS_MOTOR_CURRENT_I2C
#include "../../../feature/digipot/digipot.h" #include "../../../feature/digipot/digipot.h"
#endif #endif
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
#include "../../../feature/dac/stepper_dac.h" #include "../../../feature/dac/stepper_dac.h"
#endif #endif
@ -42,61 +42,61 @@
* M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S * M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S
*/ */
void GcodeSuite::M907() { 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()); LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int());
if (parser.seenval('B')) stepper.digipot_current(4, 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.digipot_current(i, 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 #elif HAS_MOTOR_CURRENT_PWM
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) #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 #endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) #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 #endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E) #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
#endif #endif
#if HAS_I2C_DIGIPOT #if HAS_MOTOR_CURRENT_I2C
// this one uses actual amps in floating point // 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. // Additional extruders use B,C,D for channels 4,5,6.
// TODO: Change these parameters because 'E' is used. B<index>? // TODO: Change these parameters because 'E' is used. B<index>?
for (uint8_t i = E_AXIS + 1; i < DIGIPOT_I2C_NUM_CHANNELS; i++) 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 #endif
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
if (parser.seenval('S')) { if (parser.seenval('S')) {
const float dac_percent = parser.value_float(); 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 #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>) * M908: Control digital trimpot directly (M908 P<pin> S<current>)
*/ */
void GcodeSuite::M908() { void GcodeSuite::M908() {
TERN_(HAS_DIGIPOTSS, stepper.digitalPotWrite(parser.intval('P'), parser.intval('S'))); TERN_(HAS_MOTOR_CURRENT_SPI, stepper.set_digipot_value_spi(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_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(); } #endif // HAS_MOTOR_CURRENT_DAC
void GcodeSuite::M910() { dac_commit_eeprom(); }
#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

View file

@ -823,11 +823,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 900: M900(); break; // M900: Set advance K factor. case 900: M900(); break; // M900: Set advance K factor.
#endif #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. 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. 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 909: M909(); break; // M909: Print digipot/DAC current value
case 910: M910(); break; // M910: Commit digipot/DAC value to external EEPROM case 910: M910(); break; // M910: Commit digipot/DAC value to external EEPROM
#endif #endif

View file

@ -258,9 +258,9 @@
* M900 - Get or Set Linear Advance K-factor. (Requires LIN_ADVANCE) * 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) * 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) * 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) * M908 - Control digital trimpot directly. (Requires HAS_MOTOR_CURRENT_DAC or DIGIPOTSS_PIN)
* M909 - Print digipot/DAC current value. (Requires DAC_STEPPER_CURRENT) * M909 - Print digipot/DAC current value. (Requires HAS_MOTOR_CURRENT_DAC)
* M910 - Commit digipot/DAC value to external EEPROM via I2C. (Requires DAC_STEPPER_CURRENT) * 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) * 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) * 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) * M913 - Set HYBRID_THRESHOLD speed. (Requires HYBRID_THRESHOLD)
@ -847,11 +847,11 @@ private:
static void M918(); static void M918();
#endif #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(); static void M907();
#if EITHER(HAS_DIGIPOTSS, DAC_STEPPER_CURRENT) #if EITHER(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_DAC)
static void M908(); static void M908();
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
static void M909(); static void M909();
static void M910(); static void M910();
#endif #endif

View file

@ -175,7 +175,7 @@
#endif #endif
#if EITHER(DIGIPOT_MCP4018, DIGIPOT_MCP4451) #if EITHER(DIGIPOT_MCP4018, DIGIPOT_MCP4451)
#define HAS_I2C_DIGIPOT 1 #define HAS_MOTOR_CURRENT_I2C 1
#endif #endif
// Multiple Z steppers // Multiple Z steppers

View file

@ -1976,7 +1976,7 @@
#define HAS_STEPPER_RESET 1 #define HAS_STEPPER_RESET 1
#endif #endif
#if PIN_EXISTS(DIGIPOTSS) #if PIN_EXISTS(DIGIPOTSS)
#define HAS_DIGIPOTSS 1 #define HAS_MOTOR_CURRENT_SPI 1
#endif #endif
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_Z, MOTOR_CURRENT_PWM_E) #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 #define HAS_MOTOR_CURRENT_PWM 1

View file

@ -2667,7 +2667,7 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
/** /**
* Digipot requirement * Digipot requirement
*/ */
#if HAS_I2C_DIGIPOT #if HAS_MOTOR_CURRENT_I2C
#if BOTH(DIGIPOT_MCP4018, DIGIPOT_MCP4451) #if BOTH(DIGIPOT_MCP4018, DIGIPOT_MCP4451)
#error "Enable only one of DIGIPOT_MCP4018 or DIGIPOT_MCP4451." #error "Enable only one of DIGIPOT_MCP4018 or DIGIPOT_MCP4451."
#elif !MB(MKS_SBASE) \ #elif !MB(MKS_SBASE) \

View file

@ -58,16 +58,16 @@
void menu_tmc(); void menu_tmc();
void menu_backlash(); void menu_backlash();
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
#include "../../feature/dac/stepper_dac.h" #include "../../feature/dac/stepper_dac.h"
void menu_dac() { void menu_dac() {
static xyze_uint8_t driverPercent; 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(); START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS); 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(X);
EDIT_DAC_PERCENT(Y); EDIT_DAC_PERCENT(Y);
EDIT_DAC_PERCENT(Z); EDIT_DAC_PERCENT(Z);
@ -568,7 +568,7 @@ void menu_advanced_settings() {
SUBMENU(MSG_BACKLASH, menu_backlash); SUBMENU(MSG_BACKLASH, menu_backlash);
#endif #endif
#if ENABLED(DAC_STEPPER_CURRENT) #if ENABLED(HAS_MOTOR_CURRENT_DAC)
SUBMENU(MSG_DRIVE_STRENGTH, menu_dac); SUBMENU(MSG_DRIVE_STRENGTH, menu_dac);
#endif #endif
#if HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_PWM

View file

@ -36,7 +36,7 @@
*/ */
// Change EEPROM version if the structure changes // Change EEPROM version if the structure changes
#define EEPROM_VERSION "V81" #define EEPROM_VERSION "V82"
#define EEPROM_OFFSET 100 #define EEPROM_OFFSET 100
// Check the integrity of data offsets. // Check the integrity of data offsets.
@ -365,7 +365,10 @@ typedef struct SettingsDataStruct {
// //
// HAS_MOTOR_CURRENT_PWM // 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 // CNC_COORDINATE_SYSTEMS
@ -1277,10 +1280,10 @@ void MarlinSettings::postprocess() {
{ {
_FIELD_TEST(motor_current_setting); _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); EEPROM_WRITE(stepper.motor_current_setting);
#else #else
const uint32_t no_current[3] = { 0 }; const uint32_t no_current[MOTOR_CURRENT_COUNT] = { 0 };
EEPROM_WRITE(no_current); EEPROM_WRITE(no_current);
#endif #endif
} }
@ -2110,10 +2113,16 @@ void MarlinSettings::postprocess() {
// Motor Current PWM // Motor Current PWM
// //
{ {
uint32_t motor_current_setting[3];
_FIELD_TEST(motor_current_setting); _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); 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) if (!validating)
COPY(stepper.motor_current_setting, motor_current_setting); COPY(stepper.motor_current_setting, motor_current_setting);
#endif #endif
@ -2791,9 +2800,20 @@ void MarlinSettings::reset() {
// //
#if HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_PWM
constexpr uint32_t tmp_motor_current_setting[3] = PWM_MOTOR_CURRENT; constexpr uint32_t tmp_motor_current_setting[MOTOR_CURRENT_COUNT] = PWM_MOTOR_CURRENT;
LOOP_L_N(q, 3) LOOP_L_N(q, MOTOR_CURRENT_COUNT)
stepper.digipot_current(q, (stepper.motor_current_setting[q] = tmp_motor_current_setting[q])); 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 #endif
// //
@ -3695,14 +3715,23 @@ void MarlinSettings::reset() {
#endif #endif
#endif #endif
#if HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
CONFIG_ECHO_HEADING("Stepper motor currents:"); CONFIG_ECHO_HEADING("Stepper motor currents:");
CONFIG_ECHO_START(); CONFIG_ECHO_START();
#if HAS_MOTOR_CURRENT_PWM
SERIAL_ECHOLNPAIR_P( SERIAL_ECHOLNPAIR_P(
PSTR(" M907 X"), stepper.motor_current_setting[0] PSTR(" M907 X"), stepper.motor_current_setting[0]
, SP_Z_STR, stepper.motor_current_setting[1] , SP_Z_STR, stepper.motor_current_setting[1]
, SP_E_STR, stepper.motor_current_setting[2] , 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 #endif
/** /**

View file

@ -83,10 +83,6 @@ Stepper stepper; // Singleton
#define BABYSTEPPING_EXTRA_DIR_WAIT #define BABYSTEPPING_EXTRA_DIR_WAIT
#if HAS_MOTOR_CURRENT_PWM
bool Stepper::initialized; // = false
#endif
#ifdef __AVR__ #ifdef __AVR__
#include "speed_lookuptable.h" #include "speed_lookuptable.h"
#endif #endif
@ -110,7 +106,7 @@ Stepper stepper; // Singleton
#include "../feature/dac/dac_dac084s085.h" #include "../feature/dac/dac_dac084s085.h"
#endif #endif
#if HAS_DIGIPOTSS #if HAS_MOTOR_CURRENT_SPI
#include <SPI.h> #include <SPI.h>
#endif #endif
@ -142,8 +138,12 @@ Stepper stepper; // Singleton
bool Stepper::separate_multi_axis = false; bool Stepper::separate_multi_axis = false;
#endif #endif
#if HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
uint32_t Stepper::motor_current_setting[3]; // Initialized by settings.load() 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 #endif
// private: // private:
@ -2590,8 +2590,8 @@ void Stepper::init() {
set_directions(); set_directions();
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
TERN_(HAS_MOTOR_CURRENT_PWM, initialized = true); initialized = true;
digipot_init(); digipot_init();
#endif #endif
} }
@ -2930,10 +2930,10 @@ void Stepper::report_positions() {
* Software-controlled Stepper Motor Current * Software-controlled Stepper Motor Current
*/ */
#if HAS_DIGIPOTSS #if HAS_MOTOR_CURRENT_SPI
// From Arduino DigitalPotControl example // 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 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(address); // Send the address and value via SPI
SPI.transfer(value); SPI.transfer(value);
@ -2941,7 +2941,7 @@ void Stepper::report_positions() {
//delay(10); //delay(10);
} }
#endif // HAS_DIGIPOTSS #endif // HAS_MOTOR_CURRENT_SPI
#if HAS_MOTOR_CURRENT_PWM #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) #if ANY_PIN(MOTOR_CURRENT_PWM_E, MOTOR_CURRENT_PWM_E0, MOTOR_CURRENT_PWM_E1)
case 2: case 2:
#endif #endif
digipot_current(i, motor_current_setting[i]); set_digipot_current(i, motor_current_setting[i]);
default: break; default: break;
} }
} }
@ -2968,21 +2968,22 @@ void Stepper::report_positions() {
#if !MB(PRINTRBOARD_G2) #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))
#if HAS_DIGIPOTSS motor_current_setting[driver] = current; // update motor_current_setting
const uint8_t digipot_ch[] = DIGIPOT_CHANNELS;
digitalPotWrite(digipot_ch[driver], current);
#elif HAS_MOTOR_CURRENT_PWM
if (!initialized) return; if (!initialized) return;
if (WITHIN(driver, 0, COUNT(motor_current_setting) - 1)) #if HAS_MOTOR_CURRENT_SPI
motor_current_setting[driver] = current; // update motor_current_setting
//SERIAL_ECHOLNPAIR("Digipotss current ", current);
const uint8_t digipot_ch[] = DIGIPOT_CHANNELS;
set_digipot_value_spi(digipot_ch[driver], current);
#elif HAS_MOTOR_CURRENT_PWM
#define _WRITE_CURRENT_PWM(P) analogWrite(pin_t(MOTOR_CURRENT_PWM_## P ##_PIN), 255L * current / (MOTOR_CURRENT_PWM_RANGE)) #define _WRITE_CURRENT_PWM(P) analogWrite(pin_t(MOTOR_CURRENT_PWM_## P ##_PIN), 255L * current / (MOTOR_CURRENT_PWM_RANGE))
switch (driver) { switch (driver) {
@ -3019,17 +3020,13 @@ void Stepper::report_positions() {
void Stepper::digipot_init() { void Stepper::digipot_init() {
#if HAS_DIGIPOTSS #if HAS_MOTOR_CURRENT_SPI
static const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT;
SPI.begin(); SPI.begin();
SET_OUTPUT(DIGIPOTSS_PIN); SET_OUTPUT(DIGIPOTSS_PIN);
LOOP_L_N(i, COUNT(digipot_motor_current)) { LOOP_L_N(i, COUNT(motor_current_setting))
//digitalPotWrite(digipot_ch[i], digipot_motor_current[i]); set_digipot_current(i, motor_current_setting[i]);
digipot_current(i, digipot_motor_current[i]);
}
#elif HAS_MOTOR_CURRENT_PWM #elif HAS_MOTOR_CURRENT_PWM

View file

@ -245,12 +245,18 @@ class Stepper {
static bool separate_multi_axis; static bool separate_multi_axis;
#endif #endif
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
#if HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_PWM
#ifndef PWM_MOTOR_CURRENT #ifndef PWM_MOTOR_CURRENT
#define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT #define PWM_MOTOR_CURRENT DEFAULT_PWM_MOTOR_CURRENT
#endif #endif
static uint32_t motor_current_setting[3]; #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 bool initialized; static bool initialized;
static uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
#endif #endif
// Last-moved extruder, as set when the last movement was fetched from planner // 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 // Triggered position of an axis in steps
static int32_t triggered_position(const AxisEnum axis); static int32_t triggered_position(const AxisEnum axis);
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
static void digitalPotWrite(const int16_t address, const int16_t value); static void set_digipot_value_spi(const int16_t address, const int16_t value);
static void digipot_current(const uint8_t driver, const int16_t current); static void set_digipot_current(const uint8_t driver, const int16_t current);
#endif #endif
#if HAS_MICROSTEPS #if HAS_MICROSTEPS
@ -582,7 +588,7 @@ class Stepper {
static int32_t _eval_bezier_curve(const uint32_t curr_step); static int32_t _eval_bezier_curve(const uint32_t curr_step);
#endif #endif
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
static void digipot_init(); static void digipot_init();
#endif #endif

View file

@ -34,7 +34,7 @@
// //
// I2C based DAC like on the Printrboard REVF // 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 // Channels available for DAC, For Rigidboard there are 4
#define DAC_STEPPER_ORDER { 0, 1, 2, 3 } #define DAC_STEPPER_ORDER { 0, 1, 2, 3 }

View file

@ -143,7 +143,7 @@
#endif // NO_EXTRUDRBOARD #endif // NO_EXTRUDRBOARD
// Enable control of stepper motor currents with the I2C based MCP4728 DAC used on Printrboard REVF // 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 // Set default drive strength percents if not already defined - X, Y, Z, E axis
#ifndef DAC_MOTOR_CURRENT_DEFAULT #ifndef DAC_MOTOR_CURRENT_DEFAULT

View file

@ -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> 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> HAS_STEALTHCHOP = src_filter=+<src/gcode/feature/trinamic/M569.cpp>
SR_LCD_3W_NL = SailfishLCD=https://github.com/mikeshub/SailfishLCD/archive/master.zip 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> src_filter=+<src/feature/digipot>
HAS_TMC26X = TMC26XStepper=https://github.com/trinamic/TMC26XStepper/archive/master.zip HAS_TMC26X = TMC26XStepper=https://github.com/trinamic/TMC26XStepper/archive/master.zip
src_filter=+<src/module/TMC26X.cpp> 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> 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> EXTERNAL_CLOSED_LOOP_CONTROLLER = src_filter=+<src/feature/closedloop.cpp> +<src/gcode/calibrate/M12.cpp>
USE_CONTROLLER_FAN = src_filter=+<src/feature/controllerfan.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> 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> EMERGENCY_PARSER = src_filter=+<src/feature/e_parser.cpp> -<src/gcode/control/M108_*.cpp>
I2C_POSITION_ENCODERS = src_filter=+<src/feature/encoder_i2c.cpp> I2C_POSITION_ENCODERS = src_filter=+<src/feature/encoder_i2c.cpp>