DRV2605 Haptic Driver in Real-time mode

Hey, I'm working on a haptic project vibrating an LRA motor via an adafruit DRV2605 haptic driver and getting some unexpected results, would greatly appreciate any suggestions as to where I may be going wrong. What I'm trying to achieve is a variable vibration intensity of the motor depending upon incoming data received over serial. The ultimate setup will have 5 LRAs, (and parts of the code anticipate this) though I've just got it setup with the one LRA for now.

The realtime playback mode of the driver can accept continuous realtime inputs to set the vibration intensity, which in theory should work perfectly for my needs. However, what is happening at the moment is that;

If LRAINT is 0 - LRA does not buzz - ok
If LRAINT is between 1 and about 120 - the LRA buzzes but the vibration intensity does not change
If LRAINT is over about 120 the LRA does not buzz at all

So, what I have is a vibration that seems to be either on or off, rather than increasing in intensity as LRAINT increases and then once LRAINT is over about 120, the vibration ceases, rather than continuing to increase up to 255 (I've tried reducing 255 to 200 etc in case the LRA does not work at full max intensity, but this didn't make a difference).

So I guess 2 issues;

  1. Vibration intensity not varying with LRAINT realtime value
  2. Vibration intensities over 120 result in zero vibration response.

Here's the code so far:

#include <Wire.h>
#include <Adafruit_DRV2605.h> //change to adafruit library for RTP mode

// define data received over serial
const byte numChars = 255;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

float floatsFromPC[32];

// arrange 32 received FFT bins on a log scale and map to 5 LRAs - NB LRA start / end range starts at 0
float LRA[5];
const int LRAStartRange[5] = {0, 1, 3, 7, 15};
const int LRAEndRange[5]   = {0, 2, 6, 14, 31};

int LRAINT[5];

boolean newData = false;

Adafruit_DRV2605 drv;

void setup() {

  while (!Serial);
  delay(1000);

  Wire.begin();

  Serial.begin(115200); // opens serial port, sets data rate
  drv.begin(); //initiate the i2C interface - switch to drv. initialise instruction
  drv.useLRA(); // set LRA mode
  drv.setMode(DRV2605_MODE_REALTIME); //Realtime mode enabled for direct control through software rather than hardware
  delay(2000);
  Serial.println("Arduino is Ready");
  Serial.println();

}

void loop() {

  // receive and parse the serial data into 32 FFT bins and calculate LRA ampltiudes (see defined sections below) and set the realtime value of the LRA to data received
  {
    recvWithStartEndMarkers();
    if (newData == true)
    {
      strcpy(tempChars, receivedChars);
      // this temporary copy is necessary to protect the original data
      //   because strtok() used in parseData() replaces the commas with \0
      parseData();
      showParsedData();
      LRAINT[0] = int(LRA[0]);
      LRAINT[0] = map(LRAINT[0], 0, 100, 1, 255); //maps the received value to a new range
      Serial.println(LRAINT[0]);
      drv.setRealtimeValue(LRAINT[0]); //setting function to assign the new vibration value
      newData = false;
    }
  }
}


//============

// receive a stream of data differentiated with <> start / end markers (from MaxMsp)
void recvWithStartEndMarkers()
{
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial.available() > 0 && newData == false)
  {
    rc = Serial.read();

    if (recvInProgress == true)
    {
      if (rc != endMarker)
      {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars)
        {
          ndx = numChars - 1;
        }
      }
      else
      {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker)
    {
      recvInProgress = true;
    }
  }
}

//============

// split the data into its floating point parts
void parseData()        // split the data into its parts
{
  char * strtokIndx; // this is used by strtok() as an index
  strtokIndx = strtok(tempChars, " ");     // get the first part - the string
  floatsFromPC[0] = atof(strtokIndx);     // convert this part to a float

  for (int i = 1; i < 32; i++)
  {
    strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
    floatsFromPC[i] = atof(strtokIndx);     // convert this part to a float
  }
}

// find the maximum figure in each LRA range
float maxInRange(int start, int end)
{
  float max = floatsFromPC[start];
  for (int i = start + 1; i <= end; i++)
  {
    if (floatsFromPC[i] > max)
      max = floatsFromPC[i];
  }
  return max;
}

// print FFT amplitude in each of 32 bins
void showParsedData()
{
  for (int i = 0; i < 32; i++)
  {
    //  Serial.print("Bin ");
    //  Serial.print(i+1);
    //  Serial.print(": "
    Serial.print(floatsFromPC[i]);
  }
  Serial.println();

  // print LRA amplitude as maximum in each of 5 bins consolidated logarithmically from the 32 FFTs bins
  for (int i = 0; i < 5; i++)
  {
    LRA[i] = maxInRange(LRAStartRange[i], LRAEndRange[i]) * 100;
    Serial.print("LRA");
    Serial.print(i + 1);
    Serial.print(' ');
    Serial.println(LRA[i]);
  }
}

Best
Jess

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.