Skip to content

Commit

Permalink
Digipots refactor / cleanup (MarlinFirmware#19690)
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkyhead committed Oct 16, 2020
1 parent 4ee717f commit beb17d8
Show file tree
Hide file tree
Showing 23 changed files with 239 additions and 186 deletions.
2 changes: 1 addition & 1 deletion Marlin/src/HAL/DUE/fastio/G2_PWM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/HAL/LPC1768/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
#include "feature/closedloop.h"
#endif

#if HAS_I2C_DIGIPOT
#if HAS_MOTOR_CURRENT_I2C
#include "feature/digipot/digipot.h"
#endif

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
50 changes: 26 additions & 24 deletions Marlin/src/feature/dac/dac_mcp4728.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -50,46 +52,46 @@ 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);
}
}

/**
* 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();
}

/**
* Write all input resistor values to EEPROM using SequencialWrite method.
* 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();
}

/**
* 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();
}
/**
* 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();
Expand All @@ -98,55 +100,55 @@ 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

/**
* 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();
}

/**
* FastWrite input register values - All DAC ouput update. refer to DATASHEET 5.6.1
* 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();
}

/**
* 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
25 changes: 15 additions & 10 deletions Marlin/src/feature/dac/dac_mcp4728.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
55 changes: 26 additions & 29 deletions Marlin/src/feature/dac/stepper_dac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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...
Expand All @@ -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) {
void StepperDAC::set_current_value(const uint8_t channel, uint16_t val) {
if (!dac_present) return;

NOMORE(val, 100);
NOMORE(val, uint16_t(DAC_STEPPER_MAX));

mcp4728_analogWrite(dac_order[channel], val * 0.01 * (DAC_STEPPER_MAX));
mcp4728_simpleCommand(UPDATE);
mcp4728.analogWrite(dac_order[channel], val);
mcp4728.simpleCommand(UPDATE);
}

void dac_current_raw(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);
void StepperDAC::set_current_percent(const uint8_t channel, float val) {
set_current_value(channel, _MIN(val, 100.0f) * (DAC_STEPPER_MAX) / 100.0f);
}

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); }
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 dac_current_get_percent(const AxisEnum axis) { return mcp4728_getDrvPct(dac_order[axis]); }
void dac_current_set_percents(xyze_uint8_t &pct) {
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();
Expand All @@ -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
19 changes: 12 additions & 7 deletions Marlin/src/feature/dac/stepper_dac.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
12 changes: 10 additions & 2 deletions Marlin/src/feature/digipot/digipot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Loading

0 comments on commit beb17d8

Please sign in to comment.