sh4rp3r
sh4rp3r

Reputation: 216

DRV2605 PIC16F interfacing

I'm trying to drive DRV2605L (Adafruit DRV2605L) using PIC16F18877 (DM164142 evaluation board) to control an ERM but I'm getting nowwhere. The output is dead (even with simulation using an I2C debugger). I also tried MSSP2 but got the same results. For sanity check, I used an Arduino Uno with Adafruit DRV2605 library and it is working fine.

I tried to locate the issue but no luck!

Can anyone please point out what am I doing wrong?

The code for I2C is generated by MCC 5.5 with the following configuration:

//CONFIG1
// External Oscillator mode selection bits->Oscillator not enabled
#pragma config FEXTOSC = OFF  
// Power-up default value for COSC bits->HFINTOSC (1MHz) 
#pragma config RSTOSC = HFINT1
// Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2 
#pragma config CLKOUTEN = OFF
// Clock Switch Enable bit->Writing to NOSC and NDIV is allowed   
#pragma config CSWEN = ON
// Fail-Safe Clock Monitor Enable bit->FSCM timer enabled 
#pragma config FCMEN = ON

void CLOCK_Initialize(void)
{
    // Set the CLOCK CONTROL module to the options selected in the user interface.
    //NDIV 1; NOSC HFINTOSC; 
    OSCCON1 = 0x60;
    //SOSCPWR Low power; CSWHOLD may proceed; 
    OSCCON3 = 0x0;
    //EXTOEN disabled; HFOEN disabled; MFOEN disabled; LFOEN disabled; SOSCEN disabled; ADOEN disabled; 
    OSCEN = 0x0;
    //HFFRQ 8_MHz; 
    OSCFRQ = 0x3;
    //TUN undefined; 
    OSCTUNE = 0x0;

}

void SYSTEM_Initialize(void)
{
    CLOCK_Initialize();
    PIN_MANAGER_Initialize();
    I2C1_Initialize();
    INTERRUPT_Initialize();
}

My code (based on Adafruit basic example and DRV2605 datasheet)

// drv2605.h
#define DRV2605_MODE_INTTRIG 0x00
#define TS2200_LIBRARY_A 0x01
#define ERM_OPEN_LOOP 0x20
#define ERM_MODE 0x7F
#define INTERNAL_TRIGGER_READY 0x00
#define DRV2605_R_CONTROL3 0x1D
#define DRV2605_ADDR 0x5A
#define DRV2605_R_FEEDBACK 0x1A

// drv2605.c
void initDRV2605(void) {
    __delay_us(250);
    setMode(INTERNAL_TRIGGER_READY);
    selectLibrary(TS2200_LIBRARY_A);


    registerWrite(DRV2605_R_FEEDBACK, registerRead(DRV2605_R_FEEDBACK) & ERM_MODE);
    registerWrite(DRV2605_R_CONTROL3, registerRead(DRV2605_R_CONTROL3) | ERM_OPEN_LOOP);
}

bool registerWrite(uint8_t reg, uint8_t value) {
    uint8_t data[2] = {reg, value};
    return I2C1_Write(DRV2605_ADDR, data, 2);
}

uint8_t registerRead(uint8_t reg) {
    uint8_t buffer[1] = {reg};

    I2C1_WriteRead(DRV2605_ADDR, buffer, 1, buffer, 1);
    return buffer[0];
}

void selectLibrary(uint8_t lib) {
    registerWrite(DRV2605_R_LIBRARY, lib);
}

void setMode(uint8_t mode) {
    registerWrite(DRV2605_R_MODE, mode);
}

void setWaveform(uint8_t slot, uint8_t w) {
    registerWrite(DRV2605_R_WAVESEQ1 + slot, w);
}

void go(void) {
    registerWrite(DRV2605_R_GO, 1);
}

// main.c
    SYSTEM_Initialize();
    initDRV2605();
    
int main(void) {
    SYSTEM_Initialize();
    initDRV2605();
    
    while (true) {
        // set the effect to play
        setWaveform(0, effect); // play effect
        setWaveform(1, 0); // end waveform

        // play the effect!
        go();

        // wait a bit
        __delay_ms(500);

        effect = effect + 1;
        if (effect > 100) {
            effect = 1;
        }
    }
    
    return 0;
}

Upvotes: 0

Views: 45

Answers (0)

Related Questions