Post Go back to editing

Issue reading data from X, Y and Z buffers on ADIS16223

I'm using an ADIS16223. My code to read the X, Y and Z buffers is just returning 0xFF for each byte, but all other reads and writes seem to be working. Any idea why I am having trouble getting acceleration data from the X, Y and Z buffers?    

Here is my code:

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

//
// Title: Vibration_Sensor_Tests
// Purpose: A short description of the application.
//
// Created on: 8/14/2017 at 9:50:56 AM by Physio-Control User.
// Copyright: Physio-Control. All Rights Reserved.
//
//==============================================================================

//==============================================================================
// Include files

#include <analysis.h>
#include "ni845x.h"
#include <ansi_c.h>
#include <cvirte.h>
#include <userint.h>
#include "Vibration_Sensor_Tests.h"
#include "toolbox.h"

//==============================================================================
// Constants

//==============================================================================
// Types

//==============================================================================
// Static global variables

static int panelHandle = 0;
static double bitWeight = 0.004768; //According to the datasheet, conversion factor is 4.768 mg/LSB
static int numberOfSamples = 255;

//==============================================================================
// Static functions

//==============================================================================
// Global variables

//==============================================================================
// Global functions

/// HIFN The main entry-point function.
int main (int argc, char *argv[])
{
int error = 0;

/* initialize and load resources */
nullChk (InitCVIRTE (0, argv, 0));
errChk (panelHandle = LoadPanel (0, "Vibration_Sensor_Tests.uir", PANEL));

/* display the panel and run the user interface */
errChk (DisplayPanel (panelHandle));
errChk (RunUserInterface ());

Error:
/* clean up */
if (panelHandle > 0)
DiscardPanel (panelHandle);
return 0;
}

//==============================================================================
// UI callback function prototypes

/// HIFN Exit when the user dismisses the panel.
int CVICALLBACK panelCB (int panel, int event, void *callbackData, int eventData1, int eventData2)
{
if (event == EVENT_CLOSE)
QuitUserInterface (0);
return 0;
}

int CVICALLBACK QuitCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
QuitUserInterface (0);

break;
}
return 0;
}

int CVICALLBACK INIT_SPI_COMM (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{

switch (event)
{
case EVENT_COMMIT:

uInt8 ReadData[4] = {0, 0, 0, 0};
uInt32 ReadSize = 0;
uInt8 pWriteData[4];
NiHandle DeviceHandle;
NiHandle configHandle;
uInt8 ProdIDAddress = 0x56;
int32 status = 0;
int ProductIdentifier = 0;

//status = ni845xOpen("USB0::0x3923::0x7166::01C57A4F::RAW", &DeviceHandle);
status = ni845xOpen("USB0::0x3923::0x7166::01CB2A51::RAW", &DeviceHandle);
if (status != 0) {
printf("Error Initializing NI USB-8451 Device.\nCheck to ensure that the device is plugged in.\n");
return 0;
}

status |= ni845xSpiConfigurationOpen(&configHandle);
status |= ni845xSpiConfigurationSetChipSelect (configHandle, 0);
status |= ni845xSpiConfigurationSetClockRate (configHandle, 1000); //1000 The maximum SCLK frequency is 2.25 MHz. Supported clock rates:25 kHz, 32 kHz, 40 kHz, 50 kHz, 80 kz, 100 kHz, 125 kHz, 160 kHz, 200 kHz, 250 kHz, 400 kHz, 500 kHz, 625 kHz, 800 kHz, 1 MHz, 1.25 MHz, 2.5 MHz
status |= ni845xSpiConfigurationSetClockPolarity (configHandle, kNi845xSpiClockPolarityIdleHigh);
status |= ni845xSpiConfigurationSetClockPhase (configHandle, kNi845xSpiClockPhaseSecondEdge);
status |= ni845xSpiConfigurationSetNumBitsPerSample (configHandle, 16);
status |= ni845xSpiConfigurationSetPort (configHandle, 0);
if (status != 0) {
printf("Issue configuring SPI port.");
return 0;
}

pWriteData[0] = ProdIDAddress; //0x56
pWriteData[1] = 0x00;
pWriteData[2] = 0x00;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (status != 0 || ReadSize != 4) {
printf("Issue sending the command to get Product Identifier.\n");
return 0;
} else {
ProductIdentifier = (ReadData[2] << 8) | ReadData[3];
printf("Product Identifier Value = %d\n", ProductIdentifier);
if (ProductIdentifier == 16223) { //0x3F5F in hex Note that 65535 is FFFF in hex and is incorrect
printf("The Product Identifier is Correct. \nADIS16223 Vibration Sensor is Connected!\n\n");
} else {
printf("The Product Identifier is Incorrect. ADIS16223 Vibration Sensor is Not Connected!\n\n");
}
}

ni845xSpiConfigurationClose(configHandle);
status = ni845xClose(DeviceHandle);

break;
}
return 0;
}

int CVICALLBACK GET_VIB_DATA (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{

switch (event)
{
case EVENT_COMMIT:
DeleteGraphPlot (panelHandle, PANEL_ACCEL_DATA, -1, 1);
DeleteGraphPlot (panelHandle, PANEL_FFT_DATA, -1, 1);
uInt8 ReadData[4] = {0, 0, 0, 0};
uInt32 ReadSize = 0;
uInt8 pWriteData[4];
NiHandle DeviceHandle;
NiHandle configHandle;
uInt8 CAPT_BUFFX_Address = 0x14;
uInt8 CAPT_BUFFY_Address = 0x16;
uInt8 CAPT_BUFFZ_Address = 0x18;
uInt8 CAPT_PNTR_Address = 0x9A; //address is actually 0x1A but to write to it, send 9A
uInt8 CAPT_CTRL_Address = 0x9C; //address is actually 0x1C but to write to it, send 9C
uInt8 GLOB_CMD_Address = 0xBE; //address is actually 0x3E but to write to it, send BE
uInt8 AVG_CNT_Address = 0x38;
uInt8 DIAG_STAT_Address = 0x3C;
uInt8 startCapture1 = 0xBF;
uInt8 startCapture2 = 0x08;
int32 status = 0;
//int i = 0;
uInt8 i = 0;
uint16_t tempPeakXValue = 0;
uint16_t tempPeakYValue = 0;
uint16_t tempPeakZValue = 0;
int tempDiagValue = 0;
int16 PeakXValue = 0;
int16 PeakYValue = 0;
int16 PeakZValue = 0;
double PeakXAcceleration = 0;
double PeakYAcceleration = 0;
double PeakZAcceleration = 0;
double PeakXAccelArray[1024];
double PeakYAccelArray[1024];
double PeakZAccelArray[1024];
double timeValues[1024];

//status = ni845xOpen("USB0::0x3923::0x7166::01C57A4F::RAW", &DeviceHandle);
status = ni845xOpen("USB0::0x3923::0x7166::01CB2A51::RAW", &DeviceHandle);
if (status != 0) {
printf("Error Initializing NI USB-8451 Device.\nCheck to ensure that the device is plugged in.\n");
return 0;
}

status |= ni845xSpiConfigurationOpen(&configHandle);
status |= ni845xSpiConfigurationSetChipSelect (configHandle, 0);
status |= ni845xSpiConfigurationSetClockRate (configHandle, 1000); //The maximum SCLK frequency is 2.25 MHz. Supported clock rates:25 kHz, 32 kHz, 40 kHz, 50 kHz, 80 kz, 100 kHz, 125 kHz, 160 kHz, 200 kHz, 250 kHz, 400 kHz, 500 kHz, 625 kHz, 800 kHz, 1 MHz, 1.25 MHz, 2.5 MHz
status |= ni845xSpiConfigurationSetClockPolarity (configHandle, kNi845xSpiClockPolarityIdleHigh);
status |= ni845xSpiConfigurationSetClockPhase (configHandle, kNi845xSpiClockPhaseSecondEdge);
status |= ni845xSpiConfigurationSetNumBitsPerSample (configHandle, 16);
status |= ni845xSpiConfigurationSetPort (configHandle, 0);
if (status != 0) {
printf("Issue configuring SPI port.");
return 0;
}

//Set Sampling Frequency
pWriteData[0] = AVG_CNT_Address;
pWriteData[1] = 0x00;
pWriteData[2] = 0x00;
pWriteData[3] = 0x00; //Set low-pass and band-pass filter fsc to 72.9 kHz
double Fsc = 72.9E3;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (status == 0) {
printf("Set sampling frequency to 72.9 kHz.\n\n");
} else {
printf("Error setting the AVG_CNT register!\n");
return 0;
}

//Turn on Band-Pass Filter and Set Capture Mode to Manual
pWriteData[0] = CAPT_CTRL_Address;
pWriteData[1] = 0x00;
//pWriteData[2] = 0x00;
//pWriteData[3] = 0x80; //Turn on band-pass filter, set capture mode to manual
pWriteData[2] = 0x9C;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (status == 0) {
printf("Turned on band-pass filter and set capture mode to manual.\n\n");
} else {
printf("Error setting the CAPT_CTRL register!\n");
return 0;
}

//Start Capture
pWriteData[0] = GLOB_CMD_Address; //0xBE
pWriteData[1] = 0x00;
pWriteData[2] = startCapture1; //0xBF
pWriteData[3] = startCapture2; //0x08

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (status == 0) {
printf("Sent start capture command.\n\n");
} else {
printf("Error sending the start capture command!");
return 0;
}

//Wait for data to be collected
Delay(0.5);

//Read Diagnostics Register
pWriteData[0] = DIAG_STAT_Address; //0x3C
pWriteData[1] = 0x00;
pWriteData[2] = 0x00;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (status != 0 || ReadSize != 4) {
printf("Issue sending the command to get diagnostics!\n");
return 0;
} else {
tempDiagValue = (ReadData[2] << 8) | ReadData[3];
printf("Daignostics Value = %d\n", tempDiagValue);
if (tempDiagValue == 128) { //0x0080 in hex, means data is ready and the capture is complete
printf("The Diagnostics Value is Correct!\n\n");
} else {
printf("The Diagnostics Value is Incorrect!\n\n");
}
}

//At this point, all of the data should be stored in the capture buffer registers.

//////////////////////////////////////////////////////////////////////////////////

//Initialize Pointer to Start at 0
pWriteData[0] = CAPT_PNTR_Address; //0x9A
pWriteData[1] = 0x00;
pWriteData[2] = 0x9B;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (ReadSize == 4 && status == 0) {
printf("Pass\n");
} else {
printf("Fail\n");
}

i = 0x00;
//Collect X Data
for (i = 0 ; i < numberOfSamples ; i++) {

//Create array of time values
timeValues[i] = i * (1/Fsc); //create time buffer for graphing

pWriteData[0] = CAPT_BUFFX_Address; //0x14
pWriteData[1] = 0x00;
pWriteData[2] = 0x00;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (ReadSize == 4 && status == 0) {
tempPeakXValue = (ReadData[2] << 8) | ReadData[3];
PeakXValue = -1*((~tempPeakXValue)+1);
PeakXAcceleration = (double) PeakXValue * bitWeight;
//printf("Read Data 2: %d\n", ReadData[2]);
//printf("Read Data 3: %d\n", ReadData[3]);
//printf("TEMP PEAK X AXIS Data: 0x%.4x\n", tempPeakXValue);
//printf("PEAK X AXIS Data: 0x%.4x\n", PeakXValue);
//printf("X Value = %u\n", PeakXValue);
//printf("Top X-AXIS Acceleration Point %d: %f g\n\n", i, PeakXAcceleration);
PeakXAccelArray[i] = PeakXAcceleration;
}
//printf("Status: %d\nRead Size: %d\nX i: %d\n", status, ReadSize, i);
}

//Initialize Pointer to Start at 0
pWriteData[0] = CAPT_PNTR_Address; //0x9A
pWriteData[1] = 0x00;
pWriteData[2] = 0x9B;
pWriteData[3] = 0x00;
//pWriteData[3] = i;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (ReadSize == 4 && status == 0) {
printf("Pass\n");
}

i = 0x00;
//Collect Y Data
for (i = 0 ; i < numberOfSamples ; i++) {

pWriteData[0] = CAPT_BUFFY_Address; //0x16
pWriteData[1] = 0x00;
pWriteData[2] = 0x00;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (ReadSize == 4 && status == 0) {
tempPeakYValue = (ReadData[2] << 8) | ReadData[3];
PeakYValue = -1*((~tempPeakYValue)+1);
PeakYAcceleration = (double) PeakYValue * bitWeight;
//printf("TEMP PEAK Y AXIS Data: 0x%.4x\n", tempPeakYValue);
//printf("PEAK Y AXIS Data: 0x%.4x\n", PeakYValue);
//printf("Y Value = %u\n", PeakYValue);
printf("Top Y-AXIS Acceleration Point %d: %f g\n\n", i, PeakYAcceleration);
PeakYAccelArray[i] = PeakYAcceleration;
}
//printf("Y i: %d\n",i);
}

//Initialize Pointer to Start at 0
pWriteData[0] = CAPT_PNTR_Address; //0x9A
pWriteData[1] = 0x00;
pWriteData[2] = 0x9B;
pWriteData[3] = 0x00;
//pWriteData[3] = i;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (ReadSize == 4 && status == 0) {
printf("Pass\n");
}

i = 0x00;
//Collect Z Data
for (i = 0 ; i < numberOfSamples ; i++) {

pWriteData[0] = CAPT_BUFFZ_Address; //0x18
pWriteData[1] = 0x00;
pWriteData[2] = 0x00;
pWriteData[3] = 0x00;

status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
if (ReadSize == 4 && status == 0) {
tempPeakZValue = (ReadData[2] << 8) | ReadData[3];
PeakZValue = -1*((~tempPeakZValue)+1);
PeakZAcceleration = (double) PeakZValue * bitWeight;
//printf("TEMP PEAK Z AXIS Data: 0x%.4x\n", tempPeakZValue);
//printf("PEAK Z AXIS Data: 0x%.4x\n", PeakZValue);
//printf("Z Value = %u\n", PeakZValue);
printf("Top Z-AXIS Acceleration Point %d: %f g\n\n", i, PeakZAcceleration);
PeakZAccelArray[i] = PeakZAcceleration;
}
//printf("Z i: %d\n",i);
}

PlotXY (panelHandle, PANEL_ACCEL_DATA, timeValues, PeakXAccelArray, i, VAL_DOUBLE, VAL_DOUBLE, VAL_THIN_LINE, VAL_EMPTY_SQUARE, VAL_SOLID, 1, VAL_RED);
PlotXY (panelHandle, PANEL_ACCEL_DATA, timeValues, PeakYAccelArray, i, VAL_DOUBLE, VAL_DOUBLE, VAL_THIN_LINE, VAL_EMPTY_SQUARE, VAL_SOLID, 1, VAL_BLUE);
PlotXY (panelHandle, PANEL_ACCEL_DATA, timeValues, PeakZAccelArray, i, VAL_DOUBLE, VAL_DOUBLE, VAL_THIN_LINE, VAL_EMPTY_SQUARE, VAL_SOLID, 1, VAL_GREEN);

ni845xSpiConfigurationClose(configHandle);
status = ni845xClose(DeviceHandle);

break;
}
return 0;
}

int CVICALLBACK TimerFunction (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_TIMER_TICK:
double Freq, Amp;

GetGraphCursor (panel, PANEL_FFT_DATA, 1, &Freq, &Amp);
//PowerFrequencyEstimate (Auto_Spec, numberOfSamples/2, 300, WinConst, df, 7, &Freq_Peak, &Power_Peak);

SetCtrlVal(panel, PANEL_FREQ, Freq);
SetCtrlVal(panel, PANEL_AMPL, Amp);

break;
}
return 0;
}

  • Thank you for your post and for your interest in using the ADIS16223. I am not in a position to go through all of your code in the immediate timeframe, but based on what you offered in your description, it sounds like there is not data in the buffers.  In order to solve this, you need to trigger a capture of the data, then read it.  GLOB_CMD, bit 11 provide the trigger for the data capture events.  I think that this is described on page 10 or 11 of the product's datasheet.

  • I do that in this part of the code:

    //Start Capture
    pWriteData[0] = GLOB_CMD_Address; //0xBE
    pWriteData[1] = 0x00;
    pWriteData[2] = startCapture1; //0xBF
    pWriteData[3] = startCapture2; //0x08

    status |= ni845xSpiWriteRead (DeviceHandle, configHandle, 4, pWriteData, &ReadSize, ReadData);
    if (status == 0) {
    printf("Sent start capture command.\n\n");
    } else {
    printf("Error sending the start capture command!");
    return 0;
    }

    And the program does output "Sent start capture command."

  • One more important detail that I forgot to mention. I am able to read back data for the first byte in the X buffer, but every other byte after that is 0xFF. I am wondering if there is an issue with my pointer not automatically incrementing or an issue with my read command?

  • OK, thank you for sharing that.  I have a pretty full schedule over the next couple of days, but I will keep thinking about this.  A copule of quick ideas. Apologies if you have already tried these ideas:

    1. Impose a manual delay between the trigger capture, rather than polling the status register...perhaps something is happening in that process, which is causing an interruption in the data capture/analysis process.
    2. Set up a test loop, which reads X_BUF and manually writes the next value to the BUF_PNTR.
  • Your idea about adding in the delay has helped a lot, I can now read the X buffer values. When I switch to read the Y buffer, I always get 0x8003 or 0x8007 for the returned data. When I convert that to g, I get -156.204 g. Still looking into this.

  • I noticed in the driver, that they send “0x01” as a “chip select” and they only write or read 2 bytes at a time.

     

    void ADIS16227_SetRegister8Value(unsigned char registerAddress,

                                     unsigned char registerValue)

    {

        unsigned char writeData[3]  = {0, 0, 0};

       

        writeData[0] = 0x01;    // Chip Select.

        writeData[1] = 0x80 + registerAddress;

        writeData[2] = registerValue;

        SPI_Write(writeData,2);

    }

     

    Where in the datasheet does it mention we have to send 0x01 as chip select? Also, are we only supposed to write or read 2 bytes at a time?

  • You won't find that type of instruction in the ADIS16223 datasheet, as that is one level removed from the ADIS16223 interface.  That relates to the syntax of the code, in the embedded processor, for producing the signals on the SPI line, including the CS. 

  • Did you get this reference code from somewhere in the EngineerZone? 

  • I did, actually just got everything working now! I was writing to the registers incorrectly earlier in the code!

  • Great work on this!!! Thank you for offering us a chance to help and for being so persistent. Bravo!!!