Skip to content

Commit

Permalink
Firmware support for r4.8
Browse files Browse the repository at this point in the history
 * The r4.8 uses the DRV8353 gate driver, which has slightly different
   configuration requirements than the DRV8323 used on r4.5
 * Limit gate drive strength on r4.8 boards
  • Loading branch information
jpieper committed Sep 9, 2021
1 parent 5fc3879 commit 84a4522
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 25 deletions.
4 changes: 2 additions & 2 deletions fw/bldc_servo.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ class BldcServo {
float i_gain = 20.0f; // should match csa_gain from drv8323

// PWM rise time compensation
float pwm_comp_off = 0.015;
float pwm_comp_mag = 0.005;
float pwm_comp_off = (g_measured_hw_rev <= 6) ? 0.015 : 0.048;
float pwm_comp_mag = (g_measured_hw_rev <= 6) ? 0.005 : 0.003;

// We pick a default maximum voltage based on the board revision.
float max_voltage = (g_measured_hw_rev <= 5) ? 37.0f : 46.0f;
Expand Down
76 changes: 63 additions & 13 deletions fw/drv8323.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ class Drv8323::Impl {
}

void HandleConfigUpdate() {
if (g_measured_hw_rev == 7) {
// hw rev 7 (silk r4.8) can be damaged with higher gate drive
// strength than this.
config_.idrivep_hs_ma = std::min<uint16_t>(config_.idrivep_hs_ma, 50);
config_.idriven_hs_ma = std::min<uint16_t>(config_.idriven_hs_ma, 100);
config_.idrivep_ls_ma = std::min<uint16_t>(config_.idrivep_ls_ma, 50);
config_.idriven_ls_ma = std::min<uint16_t>(config_.idriven_ls_ma, 100);
} else if (g_measured_hw_rev > 7) {
// If the gate drive strength issue has been resolved, then this
// restriction can be removed in later versions.
MJ_ASSERT(false);
}

WriteConfig();
}

Expand All @@ -187,16 +200,28 @@ class Drv8323::Impl {
return (val ? 1 : 0) << pos;
};

constexpr uint16_t idrivep_table[] = {
const bool drv8323 = g_measured_hw_rev <= 6;

constexpr uint16_t idrivep_table_drv8323[] = {
10, 30, 60, 80, 120, 140, 170, 190,
260, 330, 370, 440, 570, 680, 820, 1000,
};

constexpr uint16_t idriven_table[] = {
constexpr uint16_t idrivep_table_drv8353[] = {
50, 50, 100, 150, 300, 350, 400, 450,
550, 600, 650, 700, 850, 900, 950, 1000,
};

constexpr uint16_t idriven_table_drv8323[] = {
20, 60, 120, 160, 240, 280, 340, 380,
520, 660, 740, 880, 1140, 1360, 1640, 2000,
};

constexpr uint16_t idriven_table_drv8353[] = {
100, 100, 200, 300, 600, 700, 800, 900,
1100, 1200, 1300, 1400, 1700, 1800, 1900, 2000,
};

constexpr uint16_t tdrive_ns_table[] = {
500, 1000, 2000, 4000,
};
Expand All @@ -205,15 +230,24 @@ class Drv8323::Impl {
50, 100, 200, 400,
};

constexpr uint16_t deglitch_table[] = {
constexpr uint16_t deglitch_table_drv8323[] = {
2, 4, 6, 8,
};

constexpr uint16_t vds_lvl_table[] = {
constexpr uint16_t deglitch_table_drv8353[] = {
1, 2, 4, 8,
};

constexpr uint16_t vds_lvl_table_drv8323[] = {
60, 130, 200, 260, 310, 450, 530, 600,
680, 750, 940, 1130, 1300, 1500, 1700, 1880,
};

constexpr uint16_t vds_lvl_table_drv8353[] = {
60, 70, 80, 90, 100, 200, 300, 400,
500, 600, 700, 800, 900, 1000, 1500, 2000,
};

constexpr uint16_t csa_gain_table[] = {
5, 10, 20, 40,
};
Expand All @@ -232,6 +266,11 @@ class Drv8323::Impl {

// Drive Control Register
const uint16_t reg2 =
// OCP_ACT, which needs to be set on the drv8353 so that all 3
// half-bridges are shut down in response to a fault. That is
// the only possible behavior on the drv8323.
(drv8323 ? 0 : bit(true, 10)) |

bit(config_.dis_cpuv, 9) |
bit(config_.dis_gdf, 8) |
bit(config_.otw_rep, 7) |
Expand All @@ -241,21 +280,27 @@ class Drv8323::Impl {

const uint16_t reg3 =
(3 << 8) |
(map_choice(idrivep_table, config_.idrivep_hs_ma) << 4) |
(map_choice(idriven_table, config_.idriven_hs_ma) << 0);
(map_choice(drv8323 ? idrivep_table_drv8323 : idrivep_table_drv8353,
config_.idrivep_hs_ma) << 4) |
(map_choice(drv8323 ? idriven_table_drv8323 : idriven_table_drv8353,
config_.idriven_hs_ma) << 0);

const uint16_t reg4 =
bit(config_.cbc, 10) |
(map_choice(tdrive_ns_table, config_.tdrive_ns) << 8) |
(map_choice(idrivep_table, config_.idrivep_ls_ma) << 4) |
(map_choice(idriven_table, config_.idriven_ls_ma) << 0);
(map_choice(drv8323 ? idrivep_table_drv8323 : idrivep_table_drv8353,
config_.idrivep_ls_ma) << 4) |
(map_choice(drv8323 ? idriven_table_drv8323 : idrivep_table_drv8353,
config_.idriven_ls_ma) << 0);

const uint16_t reg5 =
bit(config_.tretry, 10) |
(map_choice(dead_time_table, config_.dead_time_ns) << 8) |
(static_cast<uint16_t>(config_.ocp_mode) << 6) |
(map_choice(deglitch_table, config_.ocp_deg_us) << 4) |
(map_choice(vds_lvl_table, config_.vds_lvl_mv) << 0);
(map_choice(drv8323 ? deglitch_table_drv8323 : deglitch_table_drv8353,
config_.ocp_deg_us) << 4) |
(map_choice(drv8323 ? vds_lvl_table_drv8323 : vds_lvl_table_drv8353,
config_.vds_lvl_mv) << 0);

const uint16_t reg6 =
bit(config_.csa_fet, 10) |
Expand All @@ -265,16 +310,21 @@ class Drv8323::Impl {
bit(config_.dis_sen, 5) |
(map_choice(sen_lvl_table, config_.sen_lvl_mv) << 0);

const uint16_t regs[] = { 0, 0, reg2, reg3, reg4, reg5, reg6 };
const uint16_t reg7 =
// This is the CAL_MODE bit, that must be 1 on the drv8353 to
// have equivalent behavior to the drv8323.
(drv8323 ? 0 : bit(true, 0));

const uint16_t regs[] = { 0, 0, reg2, reg3, reg4, reg5, reg6, reg7 };

// First set all the registers.
for (int i = 2; i <= 6; i++) {
for (int i = 2; i <= 7; i++) {
Write(i, regs[i]);
}

// Then verify that all registers got the value we want.
uint8_t fault_config = 0;
for (int i = 2; i <= 6; i++) {
for (int i = 2; i <= 7; i++) {
const auto result = Read(i);

if (result != regs[i]) {
Expand Down
14 changes: 9 additions & 5 deletions fw/drv8323.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,24 @@ class Drv8323 : public MotorDriver {


// Gate Drive HS Register
uint16_t idrivep_hs_ma = 370;
uint16_t idriven_hs_ma = 740;

// hw rev 7 boards use a drv8353, which is sensitive to damage
// ringing on the gate drives. This version requires lower gate
// drive strength to avoid damage.
uint16_t idrivep_hs_ma = (g_measured_hw_rev <= 6) ? 370 : 50;
uint16_t idriven_hs_ma = (g_measured_hw_rev <= 6) ? 740 : 100;


// Gate Drive LS Register
bool cbc = true; // Cycle-by cycle operation.
uint16_t tdrive_ns = 1000; // peak gate-current drive time
uint16_t idrivep_ls_ma = 370;
uint16_t idriven_ls_ma = 740;
uint16_t idrivep_ls_ma = (g_measured_hw_rev <= 6) ? 370 : 50;
uint16_t idriven_ls_ma = (g_measured_hw_rev <= 6) ? 740 : 100;


// OCP Control Register
bool tretry = false; // false = 4ms, true = 50us
uint16_t dead_time_ns = 50;
uint16_t dead_time_ns = (g_measured_hw_rev <= 6) ? 50 : 200;
OcpMode ocp_mode = OcpMode::kLatchedFault;
uint8_t ocp_deg_us = 4; // valid options of 2, 4, 6, 8

Expand Down
11 changes: 8 additions & 3 deletions fw/moteus_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ extern volatile uint8_t g_measured_hw_rev;
// r4.4 silk
// #define MOTEUS_HW_REV 5

// r4.5 silk
// #define MOTEUS_HW_REV 6

// The most recent version of the HW.
#ifndef MOTEUS_HW_REV
// r4.5 silk
#define MOTEUS_HW_REV 6
// r4.5b-r4.8 silk
#define MOTEUS_HW_REV 7
#endif

// The mapping between MOTEUS_HW_REV and the version pins on the
Expand All @@ -54,6 +57,7 @@ constexpr int kHardwareInterlock[] = {
0, // r4.2/r4.3 (unfortunately, indistinguishable from the interlock)
1, // r4.4
2, // r4.5
3, // r4.5b
};
#else
constexpr int kHardwareInterlock[] = {
Expand All @@ -64,6 +68,7 @@ constexpr int kHardwareInterlock[] = {
-1, // never printed for f4
-1, // never printed for f4
-1, // never printed for f4
-1, // never printed for f4
};
#endif

Expand All @@ -72,7 +77,7 @@ constexpr int kCompatibleHwRev[] = {
// 3 isn't compatible, but we forgot to rev the version pins
3,
4, 5,
6,
6, 7
};

#define DRV8323_ENABLE PA_3
Expand Down
4 changes: 2 additions & 2 deletions utils/dynamometer_drive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ class Application {
const double estimated_velocity =
(results[i].position - results[i - 1].position) / kDelayS;
// TODO: Lower this threshold.
if (std::abs(estimated_velocity - speed) > 0.18) {
if (std::abs(estimated_velocity - speed) > 0.198) {
throw mjlib::base::system_error::einval(
fmt::format("estimated speed at index {} too far off {} != {}",
i, estimated_velocity, speed));
Expand Down Expand Up @@ -1859,7 +1859,7 @@ class Application {
{ 100.0, 4.04 },
{ 20.0, 3.0 },
{ 10.0, 2.09 },
{ 5.0, 1.45 },
{ 5.0, 1.55 },
};

for (const auto test : tests) {
Expand Down

0 comments on commit 84a4522

Please sign in to comment.