This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DRV2605: DRV2605 no longer drives motors

Part Number: DRV2605

On a project that has sold hundreds of units, we occasionally have an electrical board fail, with the symptom that the motor no longer vibrates.

We've carried out a number of investigations and have come to the conclusion that in some cases the DRV2605 no longer drives the motor!

When this problem occurs, we can make a rest of our microcontroller, we can send back different firmware in the microcontroller and we were able to observe:

* I2C communication between the DRV2605 and the microcontroller is OK

* We can send the RESET_DEV command

* We can read register 0 and confirm that everything is OK

* The only way to restart the motor is to cut the power supply for at least 1 second. If the power cut lasts less than this, the DRV2605 will not drive the motor.

 

The DRV2605 init phase is as follows:

* DRV2605_EN = 0

* delay 20ms

* DRV2605_EN = 1

* delay 2ms

* send RESET_DEV (DRV_MODE = 0x80)

* delay 20ms

* Send CALIB (DRV_MODE = 0x07)

* View calibration in attached file

* Send GO (DRV_MODE = 0x01)

* Send (DRV_MODE = 0x00)

 

The vibration phase is as follows:

DRV_write(DRV_GO, 0x00);

DRV_write(DRV_WAVEFORM_SEQ_1, sequence);

DRV_write(DRV_GO, 0x01);

Motor is LRA : https://www.digikey.fr/fr/products/detail/vybronics-inc/VG1040003D/10285886

Please can you help us to explain this case ?

Regards

DRV2605.h

/* Copyright 2018 ishtob
 * Driver for DRV2605L written for QMK
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __DRV2605L_H
#define __DRV2605L_H

//#pragma once
#include "nrf_drv_twi.h"

/* Initialization settings

 * Feedback Control Settings */
#ifndef FB_ERM_LRA
#define FB_ERM_LRA 1 /* For ERM:0 or LRA:1*/
#endif
#ifndef FB_BRAKEFACTOR
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
#endif
#ifndef FB_LOOPGAIN
#define FB_LOOPGAIN 1 /* For  Low:0, Medium:1, High:2, Very High:3 */
#endif

#ifndef RATED_VOLTAGE
#define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */
#ifndef V_PEAK
#define V_PEAK 2.8
#endif
#endif

/* LRA specific settings */
#if FB_ERM_LRA == 1
#ifndef V_RMS
#define V_RMS 2.5
#endif
#ifndef V_PEAK
#define V_PEAK 2.1
#endif
#ifndef F_LRA
#define F_LRA 205
#endif
#endif

/* Library Selection */
#ifndef LIB_SELECTION
#if FB_ERM_LRA == 1
#define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */
#else
#define LIB_SELECTION 1
#endif
#endif

/* Control 1 register settings */
#ifndef DRIVE_TIME
#define DRIVE_TIME 25
#endif
#ifndef AC_COUPLE
#define AC_COUPLE 0
#endif
#ifndef STARTUP_BOOST
#define STARTUP_BOOST 1
#endif

/* Control 2 Settings */
#ifndef BIDIR_INPUT
#define BIDIR_INPUT 1
#endif
#ifndef BRAKE_STAB
#define BRAKE_STAB 1 /* Loopgain is reduced when braking is almost complete to improve stability */
#endif
#ifndef SAMPLE_TIME 
#define SAMPLE_TIME 3
#endif
#ifndef BLANKING_TIME
#define BLANKING_TIME 1
#endif
#ifndef IDISS_TIME
#define IDISS_TIME 1
#endif

/* Control 3 settings */
#ifndef NG_THRESH
#define NG_THRESH 2
#endif
#ifndef ERM_OPEN_LOOP
#define ERM_OPEN_LOOP 1
#endif
#ifndef SUPPLY_COMP_DIS
#define SUPPLY_COMP_DIS 0
#endif
#ifndef DATA_FORMAT_RTO
#define DATA_FORMAT_RTO 0
#endif
#ifndef LRA_DRIVE_MODE
#define LRA_DRIVE_MODE 0
#endif
#ifndef N_PWM_ANALOG
#define N_PWM_ANALOG 0
#endif
#ifndef LRA_OPEN_LOOP
#define LRA_OPEN_LOOP 0
#endif

/* Control 4 settings */
#ifndef ZC_DET_TIME
#define ZC_DET_TIME 0
#endif
#ifndef AUTO_CAL_TIME
#define AUTO_CAL_TIME 3
#endif

/* register defines -------------------------------------------------------- */
#define DRV2605L_BASE_ADDRESS       0x5A		/* DRV2605L Base address */
#define DRV_STATUS                  0x00
#define DRV_MODE                    0x01
#define DRV_RTP_INPUT               0x02
#define DRV_LIB_SELECTION           0x03
#define DRV_WAVEFORM_SEQ_1          0x04
#define DRV_WAVEFORM_SEQ_2          0x05
#define DRV_WAVEFORM_SEQ_3          0x06
#define DRV_WAVEFORM_SEQ_4          0x07
#define DRV_WAVEFORM_SEQ_5          0x08
#define DRV_WAVEFORM_SEQ_6          0x09
#define DRV_WAVEFORM_SEQ_7          0x0A
#define DRV_WAVEFORM_SEQ_8          0x0B
#define DRV_GO                      0x0C
#define DRV_OVERDRIVE_TIME_OFFSET   0x0D
#define DRV_SUSTAIN_TIME_OFFSET_P   0x0E
#define DRV_SUSTAIN_TIME_OFFSET_N   0x0F
#define DRV_BRAKE_TIME_OFFSET       0x10
#define DRV_AUDIO_2_VIBE_CTRL       0x11
#define DRV_AUDIO_2_VIBE_MIN_IN     0x12
#define DRV_AUDIO_2_VIBE_MAX_IN     0x13
#define DRV_AUDIO_2_VIBE_MIN_OUTDRV	0x14
#define DRV_AUDIO_2_VIBE_MAX_OUTDRV	0x15
#define DRV_RATED_VOLT              0x16
#define DRV_OVERDRIVE_CLAMP_VOLT    0x17
#define DRV_AUTO_CALIB_COMP_RESULT  0x18 
#define DRV_AUTO_CALIB_BEMF_RESULT  0x19
#define DRV_FEEDBACK_CTRL           0x1A
#define DRV_CTRL_1                  0x1B
#define DRV_CTRL_2                  0x1C
#define DRV_CTRL_3                  0x1D
#define DRV_CTRL_4                  0x1E
#define DRV_CTRL_5                  0x1F
#define DRV_OPEN_LOOP_PERIOD        0x20
#define DRV_VBAT_VOLT_MONITOR       0x21
#define DRV_LRA_RESONANCE_PERIOD    0x22

void drv2605l_twi_init (void);
void drv2605l_init(uint32_t powerPerCent);
void DRV_write(const uint8_t drv_register, const uint8_t settings);
uint8_t DRV_read(const uint8_t regaddress);
void drv2605l_pulse(const uint8_t sequence);

extern const nrf_drv_twi_t m_twi;


typedef enum DRV_EFFECT{
  clear_sequence      = 0,
  strong_click 		    = 1,
  strong_click_60 		= 2,
  strong_click_30 		= 3,
  sharp_click 		    = 4,
  sharp_click_60      = 5,
  sharp_click_30      = 6,
  soft_bump           = 7,
  soft_bump_60        = 8,
  soft_bump_30        = 9,
  dbl_click           = 10,
  dbl_click_60        = 11,
  trp_click           = 12,
  soft_fuzz           = 13,
  strong_buzz         = 14,
  alert_750ms         = 15,
  alert_1000ms        = 16,
  strong_click1       = 17,
  strong_click2_80    = 18,
  strong_click3_60    = 19,
  strong_click4_30    = 20,
  medium_click1       = 21,
  medium_click2_80    = 22,
  medium_click3_60    = 23,
  sharp_tick1         = 24,
  sharp_tick2_80      = 25,
  sharp_tick3_60      = 26,
  sh_dblclick_str     = 27,
  sh_dblclick_str_80  = 28,
  sh_dblclick_str_60  = 29,
  sh_dblclick_str_30  = 30,
  sh_dblclick_med     = 31,
  sh_dblclick_med_80  = 32,
  sh_dblclick_med_60  = 33,
  sh_dblsharp_tick    = 34,
  sh_dblsharp_tick_80 = 35,
  sh_dblsharp_tick_60 = 36,
  lg_dblclick_str     = 37,
  lg_dblclick_str_80  = 38,
  lg_dblclick_str_60  = 39,
  lg_dblclick_str_30  = 40,
  lg_dblclick_med     = 41,
  lg_dblclick_med_80  = 42,
  lg_dblclick_med_60  = 43,
  lg_dblsharp_tick    = 44,
  lg_dblsharp_tick_80 = 45,
  lg_dblsharp_tick_60 = 46,
  buzz 					= 47,
  buzz_80				= 48,
  buzz_60				= 49,
  buzz_40				= 50,
  buzz_20				= 51,
  pulsing_strong      = 52,
  pulsing_strong_80   = 53,
  pulsing_medium      = 54,
  pulsing_medium_80   = 55,
  pulsing_sharp       = 56,
  pulsing_sharp_80    = 57,
  transition_click		= 58,
  transition_click_80 = 59,
  transition_click_60	= 60,
  transition_click_40	= 61,
  transition_click_20	= 62,
  transition_click_10	= 63,
  transition_hum      = 64,
  transition_hum_80   = 65,
  transition_hum_60   = 66,
  transition_hum_40   = 67,
  transition_hum_20   = 68,
  transition_hum_10   = 69,
  transition_rampdown_long_smooth1  = 70,
  transition_rampdown_long_smooth2  = 71,
  transition_rampdown_med_smooth1   = 72,
  transition_rampdown_med_smooth2   = 73,
  transition_rampdown_short_smooth1 = 74,
  transition_rampdown_short_smooth2 = 75,
  transition_rampdown_long_sharp1   = 76,
  transition_rampdown_long_sharp2   = 77,
  transition_rampdown_med_sharp1    = 78,
  transition_rampdown_med_sharp2    = 79,
  transition_rampdown_short_sharp1  = 80,
  transition_rampdown_short_sharp2  = 81,
  transition_rampup_long_smooth1    = 82,
  transition_rampup_long_smooth2    = 83,
  transition_rampup_med_smooth1     = 84,
  transition_rampup_med_smooth2     = 85,
  transition_rampup_short_smooth1   = 86,
  transition_rampup_short_smooth2   = 87,
  transition_rampup_long_sharp1     = 88,
  transition_rampup_long_sharp2     = 89,
  transition_rampup_med_sharp1      = 90,
  transition_rampup_med_sharp2      = 91,
  transition_rampup_short_sharp1    = 92,
  transition_rampup_short_sharp2    = 93,
  transition_rampdown_long_smooth1_50  = 94,
  transition_rampdown_long_smooth2_50  = 95,
  transition_rampdown_med_smooth1_50   = 96,
  transition_rampdown_med_smooth2_50   = 97,
  transition_rampdown_short_smooth1_50 = 98,
  transition_rampdown_short_smooth2_50 = 99,
  transition_rampdown_long_sharp1_50   = 100,
  transition_rampdown_long_sharp2_50   = 101,
  transition_rampdown_med_sharp1_50    = 102,
  transition_rampdown_med_sharp2_50    = 103,
  transition_rampdown_short_sharp1_50  = 104,
  transition_rampdown_short_sharp2_50  = 105,
  transition_rampup_long_smooth1_50    = 106,
  transition_rampup_long_smooth2_50    = 107,
  transition_rampup_med_smooth1_50     = 108,
  transition_rampup_med_smooth2_50     = 109,
  transition_rampup_short_smooth1_50   = 110,
  transition_rampup_short_smooth2_50   = 111,
  transition_rampup_long_sharp1_50     = 112,
  transition_rampup_long_sharp2_50     = 113,
  transition_rampup_med_sharp1_50      = 114,
  transition_rampup_med_sharp2_50      = 115,
  transition_rampup_short_sharp1_50    = 116,
  transition_rampup_short_sharp2_50    = 117,
  long_buzz_for_programmatic_stopping  = 118,
  smooth_hum1_50 = 119,
  smooth_hum2_40 = 120,
  smooth_hum3_30 = 121,
  smooth_hum4_20 = 122,
  smooth_hum5_10 = 123,
} DRV_EFFECT;

/* Register bit array unions */

typedef union DRVREG_STATUS { /* register 0x00 */
  uint8_t Byte;
  struct {
    uint8_t OC_DETECT   :1; /* set to 1 when overcurrent event is detected */
    uint8_t OVER_TEMP   :1; /* set to 1 when device exceeds temp threshold */
    uint8_t FB_STS      :1; /* set to 1 when feedback controller has timed out */
    /* auto-calibration routine and diagnostic result
     * result  |  auto-calibation  |      diagnostic       |
     *   0     |      passed       | actuator func normal  |
     *   1     |      failed       | actuator func fault*  |
     * * actuator is not present or is shorted, timing out, or giving out–of-range back-EMF */
    uint8_t DIAG_RESULT :1;
    uint8_t             :1;
    uint8_t DEVICE_ID   :3; /* Device IDs 3: DRV2605  4: DRV2604  5: DRV2604L  6: DRV2605L */
  } Bits;
} DRVREG_STATUS;

typedef union DRVREG_MODE { /* register 0x01 */
  uint8_t Byte;
  struct {
    uint8_t MODE        :3; /* Mode setting */
    uint8_t             :3;
    uint8_t STANDBY     :1; /* 0:standby 1:ready */
  } Bits;
} DRVREG_MODE;

typedef union DRVREG_WAIT {
  uint8_t Byte;
  struct {
    uint8_t WAIT_MODE   :1; /* Set to 1 to interpret as wait for next 7 bits x10ms */
    uint8_t WAIT_TIME   :7;
  } Bits;
} DRVREG_WAIT;

typedef union DRVREG_FBR{ /* register 0x1A */
  uint8_t Byte;
  struct {
    uint8_t BEMF_GAIN    :2;
    uint8_t LOOP_GAIN    :2;
    uint8_t BRAKE_FACTOR :3;
    uint8_t ERM_LRA      :1;
  } Bits;
} DRVREG_FBR;

typedef union DRVREG_CTRL1{ /* register 0x1B */
  uint8_t Byte;
  struct {
    uint8_t C1_DRIVE_TIME    :5;
    uint8_t C1_AC_COUPLE     :1;
    uint8_t                  :1;
    uint8_t C1_STARTUP_BOOST :1;
  } Bits;
} DRVREG_CTRL1;

typedef union DRVREG_CTRL2{ /* register 0x1C */
  uint8_t Byte;
  struct {
    uint8_t C2_IDISS_TIME    :2;
    uint8_t C2_BLANKING_TIME :2;
    uint8_t C2_SAMPLE_TIME   :2;
    uint8_t C2_BRAKE_STAB    :1;
    uint8_t C2_BIDIR_INPUT   :1;
  } Bits;
} DRVREG_CTRL2;

typedef union DRVREG_CTRL3{ /* register 0x1D */
  uint8_t Byte;
  struct {
    uint8_t C3_LRA_OPEN_LOOP   :1;
    uint8_t C3_N_PWM_ANALOG    :1;
    uint8_t C3_LRA_DRIVE_MODE  :1;
    uint8_t C3_DATA_FORMAT_RTO :1;
    uint8_t C3_SUPPLY_COMP_DIS :1;
    uint8_t C3_ERM_OPEN_LOOP   :1;
    uint8_t C3_NG_THRESH       :2;
  } Bits;
} DRVREG_CTRL3;

typedef union DRVREG_CTRL4{ /* register 0x1E */
  uint8_t Byte;
  struct {
    uint8_t C4_OTP_PROGRAM     :1;
    uint8_t                    :1;
    uint8_t C4_OTP_STATUS      :1;
    uint8_t                    :1;
    uint8_t C4_AUTO_CAL_TIME   :2;
    uint8_t C4_ZC_DET_TIME     :2;
  } Bits;
} DRVREG_CTRL4;

typedef union DRVREG_CTRL5{ /* register 0x1F */
  uint8_t Byte;
  struct {
    uint8_t C5_IDISS_TIME         :2;
    uint8_t C5_BLANKING_TIME      :2;
    uint8_t C5_PLAYBACK_INTERVAL  :1;
    uint8_t C5_LRA_AUTO_OPEN_LOOP :1;
    uint8_t C5_AUTO_OL_CNT        :2;
  } Bits;
} DRVREG_CTRL5;

#endif

DRV2605.c


#include "nordic_common.h"
#include "nrf.h"
#include "ble_hci.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "app_timer.h"
#include "ble_nus.h"
#include "app_util_platform.h"
#include "bsp_btn_ble.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_delay.h"
#include "nrf_drv_twi.h"
#include "nrf_log.h"

#include "DRV2605L.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

extern bool vibreurV2;

/* TWI instance ID. */
#if TWI0_ENABLED
#define TWI_INSTANCE_ID     0
#elif TWI1_ENABLED
#define TWI_INSTANCE_ID     1
#endif
/* TWI instance. */
const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

uint8_t DRV2605L_transfer_buffer[20];
uint8_t DRV2605L_tx_register[0];
uint8_t DRV2605L_read_buffer[0];
uint8_t DRV2605L_read_register;

void drv2605l_twi_init (void)
{
    ret_code_t err_code;

    nrf_drv_twi_config_t twi_config = {
       .scl                = SCL_PIN_V1,
       .sda                = SDA_PIN_V1,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = true
    };
    if (vibreurV2)
    {
        twi_config.scl = SCL_PIN_V2;
        twi_config.sda = SDA_PIN_V2;
    }

    err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

void DRV_write(uint8_t drv_register, uint8_t settings) 
{
    ret_code_t err_code;

    DRV2605L_transfer_buffer[0] = drv_register;
    DRV2605L_transfer_buffer[1] = settings;
    err_code = nrf_drv_twi_tx(&m_twi, DRV2605L_BASE_ADDRESS, DRV2605L_transfer_buffer, 2, false);
}

uint8_t DRV_read(uint8_t regaddress) 
{
    ret_code_t err_code;

    err_code = nrf_drv_twi_tx(&m_twi, DRV2605L_BASE_ADDRESS, DRV2605L_tx_register, 1, true);
 
    err_code = nrf_drv_twi_rx(&m_twi, DRV2605L_BASE_ADDRESS, DRV2605L_read_buffer, 1);
    DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];

    return DRV2605L_read_register;
}





void drv2605l_init(uint32_t powerPerCent)
{
    uint8_t tmp;

    drv2605l_twi_init();

    if (vibreurV2)
    {
        nrf_gpio_cfg_output(DRV2605_EN_V2);
        nrf_gpio_pin_write(DRV2605_EN_V2, 0);
    }
    else
    {
        nrf_gpio_cfg_output(DRV2605_EN_V1);
        nrf_gpio_pin_write(DRV2605_EN_V1, 0);
    }
    nrf_delay_ms(20);

    if (vibreurV2)
    {
        nrf_gpio_cfg_output(DRV2605_EN_V2);
        nrf_gpio_pin_write(DRV2605_EN_V2, 1);
    }
    else
    {
        nrf_gpio_cfg_output(DRV2605_EN_V1);
        nrf_gpio_pin_write(DRV2605_EN_V1, 1);
    }
    nrf_delay_ms(2);

    DRV2605L_transfer_buffer[0] = 0x06; //RESET
    nrf_drv_twi_tx(&m_twi, 0x00/*General call*/, DRV2605L_transfer_buffer, 1, false);

  //RESET_DEV
  DRV_write(DRV_MODE,0x80); 
  nrf_delay_ms(20);

  tmp = DRV_read(DRV_STATUS);
  NRF_LOG_INFO("drv2605: %02X", tmp);

  /* 0x07 sets DRV2605 into calibration mode */
  DRV_write(DRV_MODE,0x07); 

//  DRV_write(DRV_FEEDBACK_CTRL,0xB6);
    
  #if FB_ERM_LRA == 0
    /* ERM settings */
  DRV_write(DRV_RATED_VOLT, (RATED_VOLTAGE/21.33)*1000);
  #if ERM_OPEN_LOOP == 0
  DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (((V_PEAK*(DRIVE_TIME+BLANKING_TIME+IDISS_TIME))/0.02133)/(DRIVE_TIME-0.0003))); 
  #elif ERM_OPEN_LOOP == 1
  DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196));
  #endif
  #elif FB_ERM_LRA == 1
  DRV_write(DRV_RATED_VOLT, (( (powerPerCent*V_RMS/100) * sqrt(1 - ((4 * ((150+(SAMPLE_TIME*50))*0.000001)) + 0.0003)* F_LRA)/0.02071)));
  #if LRA_OPEN_LOOP == 0
    DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, ((V_PEAK/sqrt(1-(F_LRA*0.0008))/0.02133)));
  #elif LRA_OPEN_LOOP == 1
    DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196));
  #endif
  #endif
      
  DRVREG_FBR FB_SET;
    FB_SET.Bits.ERM_LRA = FB_ERM_LRA;
    FB_SET.Bits.BRAKE_FACTOR = FB_BRAKEFACTOR;
    FB_SET.Bits.LOOP_GAIN =FB_LOOPGAIN;
    FB_SET.Bits.BEMF_GAIN = 0; /* auto-calibration populates this field*/
    DRV_write(DRV_FEEDBACK_CTRL, (uint8_t) FB_SET.Byte);
  DRVREG_CTRL1 C1_SET;
    C1_SET.Bits.C1_DRIVE_TIME = DRIVE_TIME;
    C1_SET.Bits.C1_AC_COUPLE = AC_COUPLE;
    C1_SET.Bits.C1_STARTUP_BOOST = STARTUP_BOOST;
    DRV_write(DRV_CTRL_1, (uint8_t) C1_SET.Byte);
  DRVREG_CTRL2 C2_SET;
    C2_SET.Bits.C2_BIDIR_INPUT = BIDIR_INPUT;
    C2_SET.Bits.C2_BRAKE_STAB = BRAKE_STAB;
    C2_SET.Bits.C2_SAMPLE_TIME = SAMPLE_TIME;
    C2_SET.Bits.C2_BLANKING_TIME = BLANKING_TIME;
    C2_SET.Bits.C2_IDISS_TIME = IDISS_TIME;
    DRV_write(DRV_CTRL_2, (uint8_t) C2_SET.Byte);
  DRVREG_CTRL3 C3_SET;
    C3_SET.Bits.C3_LRA_OPEN_LOOP = LRA_OPEN_LOOP;
    C3_SET.Bits.C3_N_PWM_ANALOG = N_PWM_ANALOG;
    C3_SET.Bits.C3_LRA_DRIVE_MODE = LRA_DRIVE_MODE;
    C3_SET.Bits.C3_DATA_FORMAT_RTO = DATA_FORMAT_RTO;
    C3_SET.Bits.C3_SUPPLY_COMP_DIS = SUPPLY_COMP_DIS;
    C3_SET.Bits.C3_ERM_OPEN_LOOP = ERM_OPEN_LOOP;
    C3_SET.Bits.C3_NG_THRESH = NG_THRESH;
    DRV_write(DRV_CTRL_3, (uint8_t) C3_SET.Byte);
  DRVREG_CTRL4 C4_SET;
    C4_SET.Bits.C4_ZC_DET_TIME = ZC_DET_TIME;
    C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME;
    DRV_write(DRV_CTRL_4, (uint8_t) C4_SET.Byte);
  DRV_write(DRV_LIB_SELECTION,LIB_SELECTION);
  //start autocalibration
  DRV_write(DRV_GO, 0x01);

  /* 0x00 sets DRV2605 out of standby and to use internal trigger
   * 0x01 sets DRV2605 out of standby and to use external trigger */
  DRV_write(DRV_MODE,0x00); 
  
  /* 0x06: LRA library */
  DRV_write(DRV_WAVEFORM_SEQ_1, 0x01);

  /* 0xB9: LRA, 4x brake factor, medium gain, 7.5x back EMF
   * 0x39: ERM, 4x brake factor, medium gain, 1.365x back EMF */
  
  /* TODO: setup auto-calibration as part of initiation */

}

void drv2605l_pulse(uint8_t sequence)
{
  DRV_write(DRV_GO, 0x00);
  DRV_write(DRV_WAVEFORM_SEQ_1, sequence);
  DRV_write(DRV_GO, 0x01);
}

  • Hello,

    Thank you for reaching out. Can you provide detail on when you are seeing the failure? Does the driver function correctly and then stop working when you try to send a waveform?

    Regards,
    Sydney Northcutt 

  • Hello,

    Unfortunately, I don't know when it stops working! The customer calls me and says: "the vibrator doesn't work any more", but I have no way of knowing if the fault occurs when an order is sent, or if it's when the battery is slightly discharged, or anything else.

    However, what I do observe is that when the customer sends the device back to me, the battery is fully charged, and everything else in the system is working properly.

    When I put the oscilloscope on the SDA and SCL pins, the signals to the DRV2605 are sent.

    When the microcontroller restarts, I query register 0x00 to make sure that the DRV2605 is responding correctly, and it is.

    However, when I send a sequence, the motor doesn't move.

    If I short the battery (it's protected), the board restarts but the motor still doesn't work.

    On the other hand, if I remove the battery for 1 or 2 seconds, the board restarts and the vibrator works perfectly...

    I currently have 500 devices in service and the problem has been identified about 10 times, on 10 different devices.

    Regards,

    Gaétan

  • Hello,

    Can you probe the power supply pins before you take out the battery and take a screen shot when you take out the battery? There might be some time for the power to fully go to 0 which is why the battery has to be out for a minimum amount of time. If the battery is put back in before these pins are zero the device would not reset. 

    What do you read back when you read 0x00? This register has some flags that might point to an issue. 

    Also, when the device powers up there is a 250us startup sequence where some registers are set which needs to be done before sending any writes to the device. Since it is so fast it likely is not your issue but is good to double check.

    Hope this helps!

    Regards,
    Sydney Northcutt 

  • Hello,

    Unfortunately, I can't reproduce the problem, I have about 1 device every 2 months with this problem.

    When I mention the DR2605 power failure, it is to specify that the DEV_RESET command does not seem to be identical to a BOR, despite what appears in the datasheet on page 19.

    When I read register 0x00, the value returned is 0xE0.

    Regards,

    Gaétan

  • Hi,

    Without being able to replicate the failure, it is difficult to do any debugging. Knowing details like when the failure happens and what the device is seeing is crucial in fixing the problem, but we can work to fix the issue that you are seeing on the board. If you find a way to replicate the issue we can dive into the root cause. 

    The DEV_RESET register should go back to 0 once the reset is complete, otherwise it is not finished. After you pull this high, does it ever go back to 0?

    Regards,
    Sydney Northcutt 

  • Hi,

    I confirm that DEV_RESET returns to 0.

    My feeling is that there is a stage in the DRV2605 that is only reset by a power failure. Therefore, using DEV_RESET does not allow resetting...

    Is there an errata sheet for this component?

    Regards,

    Gaétan

  • Hello,

    Since you are reading back 0xE0 from 0x00 I assume you are using DRV2605L, but want to double check as you have been stating DRV2605. There is not an errata sheet for either of these devices.

    There are two states in the DRV2605L where it would need to be power cycled:

    This device has an I2C watchdog timer that resets communication after 4.33ms of no interaction, but this feature is not available in the standby state so if communication is lost in this state the device has to be power cycled to reestablish communication. I believe this could be the root cause if failures are seen after the device was previously working. (Section 8.3.11 in the DRV2605L datasheet)

    Another time when power cycling might be necessary is due to the Vdd slew rate. From the DRV2605L datasheet, "If the VDD ramp-up rate is slower than 3.6 kV/s, then the device can fall into an unknown state. In such a situation, to return to the initial default state the device must be power cycled with a VDD ramp-up rate that is faster than 3.6 kV/s." This could be a possible cause if the issue is seen right after power up as the slew rate could be close to this value and have variance that causes failures. (Section 8.3.12.4 in the DRV2605L datasheet)

    Regards,
    Sydney Northcutt