0
\$\begingroup\$

I want to create a C++ (or C) program that reads in a stream of Quaternion data from the bno055 Adafruit chip.

My set-up at the moment has an Ubuntu PC as the controller. Plugged into the PC is a USB to UART breakout bridge which creates a serial port that (in theory) can be opened and read from in /dev/ttyUSB*. The orientation sensor is then wired into the UART end of the bridge (via a breadboard) in accordance with the wiring diagram found on this Adafruit webpage, meaning the UART bridge has replaced the Raspberry Pi pinouts. In short: Linux Machine -> USB -> UART -> breadboard -> Orientation Sensor

Currently, having installed the D2XX drivers for the FTDI chip (the chip in the USB bridge) and having made sure it is running these drivers by unloading the default drivers when the USB bridge is connected (sudo rmmod ftdi_sio & sudo rmmod usbserial) I can run provided example code that is included with D2XX drivers that reads device data using EEPROM data methods. The files that do this are the following:

main.c

/*
    To build use the following gcc statement 
    (assuming you have the d2xx library in the /usr/local/lib directory).
    gcc -o read main.c -L. -lftd2xx -Wl,-rpath,/usr/local/lib
    */    

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "../../ftd2xx.h"

int main(int argc, char *argv[])
{
    FT_STATUS   ftStatus;
    FT_HANDLE   ftHandle0;
    int iport;
    static FT_PROGRAM_DATA Data;
    static FT_DEVICE ftDevice;
    DWORD libraryVersion = 0;
    int retCode = 0;

    ftStatus = FT_GetLibraryVersion(&libraryVersion);
    if (ftStatus == FT_OK)
    {
        printf("Library version = 0x%x\n", (unsigned int)libraryVersion);
    }
    else
    {
        printf("Error reading library version.\n");
        return 1;
    }

    if(argc > 1) {
        sscanf(argv[1], "%d", &iport);
    }
    else {
        iport = 0;
    }
    printf("Opening port %d\n", iport);

    ftStatus = FT_Open(iport, &ftHandle0);
    if(ftStatus != FT_OK) {
        /* 
            This can fail if the ftdi_sio driver is loaded
            use lsmod to check this and rmmod ftdi_sio to remove
            also rmmod usbserial
         */
        printf("FT_Open(%d) failed\n", iport);
        return 1;
    }

    printf("FT_Open succeeded.  Handle is %p\n", ftHandle0);

    ftStatus = FT_GetDeviceInfo(ftHandle0,
                                &ftDevice,
                                NULL,
                                NULL,
                                NULL,
                                NULL); 
    if (ftStatus != FT_OK) 
    { 
        printf("FT_GetDeviceType FAILED!\n");
        retCode = 1;
        goto exit;
    }  

    printf("FT_GetDeviceInfo succeeded.  Device is type %d.\n", 
           (int)ftDevice);

    /* MUST set Signature1 and 2 before calling FT_EE_Read */
    Data.Signature1 = 0x00000000;
    Data.Signature2 = 0xffffffff;
    Data.Manufacturer = (char *)malloc(256); /* E.g "FTDI" */
    Data.ManufacturerId = (char *)malloc(256); /* E.g. "FT" */
    Data.Description = (char *)malloc(256); /* E.g. "USB HS Serial Converter" */
    Data.SerialNumber = (char *)malloc(256); /* E.g. "FT000001" if fixed, or NULL */
    if (Data.Manufacturer == NULL ||
        Data.ManufacturerId == NULL ||
        Data.Description == NULL ||
        Data.SerialNumber == NULL)
    {
        printf("Failed to allocate memory.\n");
        retCode = 1;
        goto exit;
    }

    ftStatus = FT_EE_Read(ftHandle0, &Data);
    if(ftStatus != FT_OK) {
        printf("FT_EE_Read failed\n");
        retCode = 1;
        goto exit;
    }

    printf("FT_EE_Read succeeded.\n\n");

    printf("Signature1 = %d\n", (int)Data.Signature1);          
    printf("Signature2 = %d\n", (int)Data.Signature2);          
    printf("Version = %d\n", (int)Data.Version);                

    printf("VendorId = 0x%04X\n", Data.VendorId);               
    printf("ProductId = 0x%04X\n", Data.ProductId);
    printf("Manufacturer = %s\n", Data.Manufacturer);           
    printf("ManufacturerId = %s\n", Data.ManufacturerId);       
    printf("Description = %s\n", Data.Description);         
    printf("SerialNumber = %s\n", Data.SerialNumber);           
    printf("MaxPower = %d\n", Data.MaxPower);               
    printf("PnP = %d\n", Data.PnP) ;                    
    printf("SelfPowered = %d\n", Data.SelfPowered);         
    printf("RemoteWakeup = %d\n", Data.RemoteWakeup);           

    if (ftDevice == FT_DEVICE_BM)
    {
        /* Rev4 (FT232B) extensions */
        printf("BM:\n");
        printf("---\n");
        printf("\tRev4 = 0x%X\n", Data.Rev4);                   
        printf("\tIsoIn = 0x%X\n", Data.IsoIn);             
        printf("\tIsoOut = 0x%X\n", Data.IsoOut);               
        printf("\tPullDownEnable = 0x%X\n", Data.PullDownEnable);       
        printf("\tSerNumEnable = 0x%X\n", Data.SerNumEnable);           
        printf("\tUSBVersionEnable = 0x%X\n", Data.USBVersionEnable);       
        printf("\tUSBVersion = 0x%X\n", Data.USBVersion);
    }

    if (ftDevice == FT_DEVICE_2232C) 
    {
        /* Rev 5 (FT2232C) extensions */
        printf("2232RC:\n");
        printf("-------\n");
        printf("\tRev5 = 0x%X\n", Data.Rev5);                   
        printf("\tIsoInA = 0x%X\n", Data.IsoInA);               
        printf("\tIsoInB = 0x%X\n", Data.IsoInB);               
        printf("\tIsoOutA = 0x%X\n", Data.IsoOutA);             
        printf("\tIsoOutB = 0x%X\n", Data.IsoOutB);             
        printf("\tPullDownEnable5 = 0x%X\n", Data.PullDownEnable5);     
        printf("\tSerNumEnable5 = 0x%X\n", Data.SerNumEnable5);     
        printf("\tUSBVersionEnable5 = 0x%X\n", Data.USBVersionEnable5); 
        printf("\tUSBVersion5 = 0x%X\n", Data.USBVersion5);         
        printf("\tAIsHighCurrent = 0x%X\n", Data.AIsHighCurrent);       
        printf("\tBIsHighCurrent = 0x%X\n", Data.BIsHighCurrent);       
        printf("\tIFAIsFifo = 0x%X\n", Data.IFAIsFifo);         
        printf("\tIFAIsFifoTar = 0x%X\n", Data.IFAIsFifoTar);           
        printf("\tIFAIsFastSer = 0x%X\n", Data.IFAIsFastSer);           
        printf("\tAIsVCP = 0x%X\n", Data.AIsVCP);               
        printf("\tIFBIsFifo = 0x%X\n", Data.IFBIsFifo);         
        printf("\tIFBIsFifoTar = 0x%X\n", Data.IFBIsFifoTar);           
        printf("\tIFBIsFastSer = 0x%X\n", Data.IFBIsFastSer);           
        printf("\tBIsVCP = 0x%X\n", Data.BIsVCP);
    }

    if (ftDevice == FT_DEVICE_232R)
    {
        /* Rev 6 (FT232R) extensions */
        printf("232R:\n");
        printf("-----\n");
        printf("\tUseExtOsc = 0x%X\n", Data.UseExtOsc);         // Use External Oscillator
        printf("\tHighDriveIOs = 0x%X\n", Data.HighDriveIOs);           // High Drive I/Os
        printf("\tEndpointSize = 0x%X\n", Data.EndpointSize);           // Endpoint size

        printf("\tPullDownEnableR = 0x%X\n", Data.PullDownEnableR);     // non-zero if pull down enabled
        printf("\tSerNumEnableR = 0x%X\n", Data.SerNumEnableR);     // non-zero if serial number to be used

        printf("\tInvertTXD = 0x%X\n", Data.InvertTXD);         // non-zero if invert TXD
        printf("\tInvertRXD = 0x%X\n", Data.InvertRXD);         // non-zero if invert RXD
        printf("\tInvertRTS = 0x%X\n", Data.InvertRTS);         // non-zero if invert RTS
        printf("\tInvertCTS = 0x%X\n", Data.InvertCTS);         // non-zero if invert CTS
        printf("\tInvertDTR = 0x%X\n", Data.InvertDTR);         // non-zero if invert DTR
        printf("\tInvertDSR = 0x%X\n", Data.InvertDSR);         // non-zero if invert DSR
        printf("\tInvertDCD = 0x%X\n", Data.InvertDCD);         // non-zero if invert DCD
        printf("\tInvertRI = 0x%X\n", Data.InvertRI);               // non-zero if invert RI

        printf("\tCbus0 = 0x%X\n", Data.Cbus0);             // Cbus Mux control
        printf("\tCbus1 = 0x%X\n", Data.Cbus1);             // Cbus Mux control
        printf("\tCbus2 = 0x%X\n", Data.Cbus2);             // Cbus Mux control
        printf("\tCbus3 = 0x%X\n", Data.Cbus3);             // Cbus Mux control
        printf("\tCbus4 = 0x%X\n", Data.Cbus4);             // Cbus Mux control

        printf("\tRIsD2XX = 0x%X\n", Data.RIsD2XX); // non-zero if using D2XX
    }   


exit:
    free(Data.Manufacturer);
    free(Data.ManufacturerId);
    free(Data.Description);
    free(Data.SerialNumber);
    FT_Close(ftHandle0);
    printf("Returning %d\n", retCode);
    return retCode;
}

and eeprom-read.c

/*
 * FT_EEPROM_Read demonstration.
 * Dumps the EEPROM fields of any connected FTDI device.
 *
 * Copy libftd2xx.a, ftd2xx.h, WinTypes.h into current directory.
 *
 * Compile:
 *     cc eeprom-read.c -L. -lftd2xx -lpthread
 *
 * On Mac, the above line needs these extra dependencies:
 *     -lobjc -framework IOKit -framework CoreFoundation
 *
 * Run:
 *     sudo ./a.out
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "ftd2xx.h"



typedef union Eeprom_Generic
{
    FT_EEPROM_232B     b;
    FT_EEPROM_232R     r;
    FT_EEPROM_232H     singleH;
    FT_EEPROM_2232     dual;
    FT_EEPROM_2232H    dualH;
    FT_EEPROM_4232H    quadH;
    FT_EEPROM_X_SERIES x;
}
Eeprom_Generic;



static const char *deviceName(FT_DEVICE deviceType)
{
    switch(deviceType)
    {
        default:
            return "Unknown";

        case FT_DEVICE_BM:
            return "232 B";

        case FT_DEVICE_2232C:
            return "Dual 232";

        case FT_DEVICE_232R:
            return "232 R";

        case FT_DEVICE_2232H:
            return "Dual Hi-Speed 232";

        case FT_DEVICE_4232H:
            return "Quad Hi-Speed 232";

        case FT_DEVICE_232H:
            return "Hi-Speed 232";

        case FT_DEVICE_X_SERIES:
            return "X Series";
    }
}



static void displayHeader (FT_EEPROM_HEADER *header)
{
    printf("deviceType: %s\n", deviceName(header->deviceType));

    printf("VendorId: %04x\n", header->VendorId);
    printf("ProductId: %04x\n", header->ProductId);
    printf("SerNumEnable: %02x\n", header->SerNumEnable);

    printf("MaxPower: %04x\n", header->MaxPower);
    printf("SelfPowered: %02x\n", header->SelfPowered);
    printf("RemoteWakeup: %02x\n", header->RemoteWakeup);

    printf("PullDownEnable: %02x\n", header->PullDownEnable);
}



static void displayDual (FT_EEPROM_2232 *dual)
{
    printf("AIsHighCurrent: %02x\n", dual->AIsHighCurrent);
    printf("BIsHighCurrent: %02x\n", dual->BIsHighCurrent);

    printf("AIsFifo: %02x\n", dual->AIsFifo);
    printf("AIsFifoTar: %02x\n", dual->AIsFifoTar);
    printf("AIsFastSer: %02x\n", dual->AIsFastSer);
    printf("BIsFifo: %02x\n", dual->BIsFifo);
    printf("BIsFifoTar: %02x\n", dual->BIsFifoTar);
    printf("BIsFastSer: %02x\n", dual->BIsFastSer);

    printf("ADriverType: %02x\n", dual->ADriverType);
    printf("BDriverType: %02x\n", dual->BDriverType);
}



static void displayR (FT_EEPROM_232R *r)
{
    printf("IsHighCurrent: %02x\n", r->IsHighCurrent);

    printf("UseExtOsc: %02x\n", r->UseExtOsc);
    printf("InvertTXD: %02x\n", r->InvertTXD);
    printf("InvertRXD: %02x\n", r->InvertRXD);
    printf("InvertRTS: %02x\n", r->InvertRTS);
    printf("InvertCTS: %02x\n", r->InvertCTS);
    printf("InvertDTR: %02x\n", r->InvertDTR);
    printf("InvertDSR: %02x\n", r->InvertDSR);
    printf("InvertDCD: %02x\n", r->InvertDCD);
    printf("InvertRI: %02x\n", r->InvertRI);
    printf("Cbus0: %02x\n", r->Cbus0);
    printf("Cbus1: %02x\n", r->Cbus1);
    printf("Cbus2: %02x\n", r->Cbus2);
    printf("Cbus3: %02x\n", r->Cbus3);
    printf("Cbus4: %02x\n", r->Cbus4);

    printf("DriverType: %02x\n", r->DriverType);
}



static void displayDualH (FT_EEPROM_2232H *dualH)
{
    printf("ALSlowSlew: %02x\n", dualH->ALSlowSlew);
    printf("ALSchmittInput: %02x\n", dualH->ALSchmittInput);
    printf("ALDriveCurrent: %02x\n", dualH->ALDriveCurrent);
    printf("AHSlowSlew: %02x\n", dualH->AHSlowSlew);
    printf("AHSchmittInput: %02x\n", dualH->AHSchmittInput);
    printf("AHDriveCurrent: %02x\n", dualH->AHDriveCurrent);
    printf("BLSlowSlew: %02x\n", dualH->BLSlowSlew);
    printf("BLSchmittInput: %02x\n", dualH->BLSchmittInput);
    printf("BLDriveCurrent: %02x\n", dualH->BLDriveCurrent);
    printf("BHSlowSlew: %02x\n", dualH->BHSlowSlew);
    printf("BHSchmittInput: %02x\n", dualH->BHSchmittInput);
    printf("BHDriveCurrent: %02x\n", dualH->BHDriveCurrent);

    printf("AIsFifo: %02x\n", dualH->AIsFifo);
    printf("AIsFifoTar: %02x\n", dualH->AIsFifoTar);
    printf("AIsFastSer: %02x\n", dualH->AIsFastSer);
    printf("BIsFifo: %02x\n", dualH->BIsFifo);
    printf("BIsFifoTar: %02x\n", dualH->BIsFifoTar);
    printf("BIsFastSer: %02x\n", dualH->BIsFastSer);
    printf("PowerSaveEnable: %02x\n", dualH->PowerSaveEnable);

    printf("ADriverType: %02x\n", dualH->ADriverType);
    printf("BDriverType: %02x\n", dualH->BDriverType);
}



static void displayQuadH (FT_EEPROM_4232H *quadH)
{
    printf("ASlowSlew: %02x\n", quadH->ASlowSlew);
    printf("ASchmittInput: %02x\n", quadH->ASchmittInput);
    printf("ADriveCurrent: %02x\n", quadH->ADriveCurrent);
    printf("BSlowSlew: %02x\n", quadH->BSlowSlew);
    printf("BSchmittInput: %02x\n", quadH->BSchmittInput);
    printf("BDriveCurrent: %02x\n", quadH->BDriveCurrent);
    printf("CSlowSlew: %02x\n", quadH->CSlowSlew);
    printf("CSchmittInput: %02x\n", quadH->CSchmittInput);
    printf("CDriveCurrent: %02x\n", quadH->CDriveCurrent);
    printf("DSlowSlew: %02x\n", quadH->DSlowSlew);
    printf("DSchmittInput: %02x\n", quadH->DSchmittInput);
    printf("DDriveCurrent: %02x\n", quadH->DDriveCurrent);

    printf("ARIIsTXDEN: %02x\n", quadH->ARIIsTXDEN);
    printf("BRIIsTXDEN: %02x\n", quadH->BRIIsTXDEN);
    printf("CRIIsTXDEN: %02x\n", quadH->CRIIsTXDEN);
    printf("DRIIsTXDEN: %02x\n", quadH->DRIIsTXDEN);

    printf("ADriverType: %02x\n", quadH->ADriverType);
    printf("BDriverType: %02x\n", quadH->BDriverType);
    printf("CDriverType: %02x\n", quadH->CDriverType);
    printf("DDriverType: %02x\n", quadH->DDriverType);
}



static void displaySingleH (FT_EEPROM_232H *singleH)
{
    printf("ACSlowSlew: %02x\n", singleH->ACSlowSlew);
    printf("ACSchmittInput: %02x\n", singleH->ACSchmittInput);
    printf("ACDriveCurrent: %02x\n", singleH->ACDriveCurrent);
    printf("ADSlowSlew: %02x\n", singleH->ADSlowSlew);
    printf("ADSchmittInput: %02x\n", singleH->ADSchmittInput);
    printf("ADDriveCurrent: %02x\n", singleH->ADDriveCurrent);

    printf("Cbus0: %02x\n", singleH->Cbus0);
    printf("Cbus1: %02x\n", singleH->Cbus1);
    printf("Cbus2: %02x\n", singleH->Cbus2);
    printf("Cbus3: %02x\n", singleH->Cbus3);
    printf("Cbus4: %02x\n", singleH->Cbus4);
    printf("Cbus5: %02x\n", singleH->Cbus5);
    printf("Cbus6: %02x\n", singleH->Cbus6);
    printf("Cbus7: %02x\n", singleH->Cbus7);
    printf("Cbus8: %02x\n", singleH->Cbus8);
    printf("Cbus9: %02x\n", singleH->Cbus9);

    printf("FT1248Cpol: %02x\n", singleH->FT1248Cpol);
    printf("FT1248Lsb: %02x\n", singleH->FT1248Lsb);
    printf("FT1248FlowControl: %02x\n", singleH->FT1248FlowControl);

    printf("IsFifo: %02x\n", singleH->IsFifo);
    printf("IsFifoTar: %02x\n", singleH->IsFifoTar);
    printf("IsFastSer: %02x\n", singleH->IsFastSer);
    printf("IsFT1248    : %02x\n", singleH->IsFT1248    );
    printf("PowerSaveEnable: %02x\n", singleH->PowerSaveEnable);

    printf("DriverType: %02x\n", singleH->DriverType);
}



static void displayX (FT_EEPROM_X_SERIES *x)
{
    printf("ACSlowSlew: %02x\n", x->ACSlowSlew);
    printf("ACSchmittInput: %02x\n", x->ACSchmittInput);
    printf("ACDriveCurrent: %02x\n", x->ACDriveCurrent);
    printf("ADSlowSlew: %02x\n", x->ADSlowSlew);
    printf("ADSchmittInput: %02x\n", x->ADSchmittInput);
    printf("ADDriveCurrent: %02x\n", x->ADDriveCurrent);

    printf("Cbus0: %02x\n", x->Cbus0);
    printf("Cbus1: %02x\n", x->Cbus1);
    printf("Cbus2: %02x\n", x->Cbus2);
    printf("Cbus3: %02x\n", x->Cbus3);
    printf("Cbus4: %02x\n", x->Cbus4);
    printf("Cbus5: %02x\n", x->Cbus5);
    printf("Cbus6: %02x\n", x->Cbus6);

    printf("InvertTXD: %02x\n", x->InvertTXD);
    printf("InvertRXD: %02x\n", x->InvertRXD);
    printf("InvertRTS: %02x\n", x->InvertRTS);
    printf("InvertCTS: %02x\n", x->InvertCTS);
    printf("InvertDTR: %02x\n", x->InvertDTR);
    printf("InvertDSR: %02x\n", x->InvertDSR);
    printf("InvertDCD: %02x\n", x->InvertDCD);
    printf("InvertRI: %02x\n", x->InvertRI);

    printf("BCDEnable: %02x\n", x->BCDEnable);
    printf("BCDForceCbusPWREN: %02x\n", x->BCDForceCbusPWREN);
    printf("BCDDisableSleep: %02x\n", x->BCDDisableSleep);

    printf("I2CSlaveAddress: %04x\n", x->I2CSlaveAddress);
    printf("I2CDeviceId: %04x\n", x->I2CDeviceId);
    printf("I2CDisableSchmitt: %02x\n", x->I2CDisableSchmitt);

    printf("FT1248Cpol: %02x\n", x->FT1248Cpol);
    printf("FT1248Lsb: %02x\n", x->FT1248Lsb);
    printf("FT1248FlowControl: %02x\n", x->FT1248FlowControl);

    printf("RS485EchoSuppress: %02x\n", x->RS485EchoSuppress);
    printf("PowerSaveEnable: %02x\n", x->PowerSaveEnable);

    printf("DriverType: %02x\n", x->DriverType);
}



static int readEeprom (DWORD locationId, FT_DEVICE deviceType)
{
    int                  success = 0;
    FT_STATUS            ftStatus;
    FT_HANDLE            ftHandle = (FT_HANDLE)NULL;
    char                 manufacturer[64];
    char                 manufacturerId[64];
    char                 description[64];
    char                 serialNumber[64];
    Eeprom_Generic      *eeprom = NULL;
    FT_EEPROM_HEADER    *header;

    ftStatus = FT_OpenEx((PVOID)(uintptr_t)locationId,
                         FT_OPEN_BY_LOCATION,
                         &ftHandle);
    if (ftStatus != FT_OK)
    {
        printf("FT_OpenEx failed (error code %d)\n", (int)ftStatus);
        goto exit;
    }

    /* Allocate enough to hold biggest EEPROM structure */
    eeprom = calloc(1, sizeof(*eeprom));
    if (eeprom == NULL)
    {
        printf("Allocation failure.\n");
        goto exit;
    }

    /* EEPROM_HEADER is first member of every type of eeprom */
    header = (FT_EEPROM_HEADER *)eeprom;
    header->deviceType = deviceType;

    manufacturer[0] = '\0';
    manufacturerId[0] = '\0';
    description[0] = '\0';
    serialNumber[0] = '\0';

    ftStatus = FT_EEPROM_Read(ftHandle,
                              eeprom,
                              sizeof(*eeprom),
                              manufacturer,
                              manufacturerId,
                              description,
                              serialNumber);
    if (ftStatus != FT_OK)
    {
        printf("FT_EEPROM_Read failed (error code %d)\n", (int)ftStatus);
        goto exit;
    }

    printf("Manufacturer = %s\n", manufacturer);
    printf("ManufacturerId = %s\n", manufacturerId);
    printf("Description = %s\n", description);
    printf("Serial number = %s\n", serialNumber);

    displayHeader((FT_EEPROM_HEADER *)eeprom);

    switch(deviceType)
    {
        default:
        case FT_DEVICE_BM:
            // No further info to display
            break;

        case FT_DEVICE_2232C:
            displayDual(&eeprom->dual);
            break;

        case FT_DEVICE_232R:
            displayR(&eeprom->r);
            break;

        case FT_DEVICE_2232H:
            displayDualH(&eeprom->dualH);
            break;

        case FT_DEVICE_4232H:
            displayQuadH(&eeprom->quadH);
            break;

        case FT_DEVICE_232H:
            displaySingleH(&eeprom->singleH);
            break;

        case FT_DEVICE_X_SERIES:
            displayX(&eeprom->x);
            break;
    }

    printf("\n");

    // Success
    success = 1;

exit:
    (void)FT_Close(ftHandle);
    free(eeprom);
    return success;
}



int main (int argc, char *argv[])
{
    FT_STATUS                 ftStatus;
    FT_DEVICE_LIST_INFO_NODE *devInfo = NULL;
    DWORD                     numDevs = 0;
    int                       i;
    int                       retCode = 0;

    /* Unused parameters */
    (void)argc;
    (void)argv;

    /* Discover how many FTDI devices are connected */
    ftStatus = FT_CreateDeviceInfoList(&numDevs);
    if (ftStatus != FT_OK)
    {
        printf("FT_CreateDeviceInfoList failed (error code %d)\n",
               (int)ftStatus);
        goto exit;
    }

    if (numDevs == 0)
    {
        printf("No devices connected.\n");
        goto exit;
    }

    /* Allocate storage */
    devInfo = calloc((size_t)numDevs,
                     sizeof(FT_DEVICE_LIST_INFO_NODE));
    if (devInfo == NULL)
    {
        printf("Allocation failure.\n");
        goto exit;
    }

    /* Populate the list of info nodes */
    ftStatus = FT_GetDeviceInfoList(devInfo, &numDevs);
    if (ftStatus != FT_OK)
    {
        printf("FT_GetDeviceInfoList failed (error code %d)\n",
               (int)ftStatus);
        goto exit;
    }

    /* Display info (including EEPROM fields) for each connected FTDI device */
    for (i = 0; i < (int)numDevs; i++)
    {
        printf("Device %d:\n",i);
        printf("  Flags = 0x%x\n",devInfo[i].Flags);
        printf("  Type = 0x%x\n",devInfo[i].Type);
        printf("  ID = 0x%04x\n",devInfo[i].ID);
        printf("  LocId = 0x%x\n",devInfo[i].LocId);
        printf("  SerialNumber = %s\n",devInfo[i].SerialNumber);
        printf("  Description = %s\n",devInfo[i].Description);
        printf("  ftHandle = %p\n",devInfo[i].ftHandle);
        if (!readEeprom(devInfo[i].LocId, devInfo[i].Type))
        {
            goto exit;
        }
    }

exit:
    free(devInfo);
    return retCode;
}

With reference to the header file ftd2xx.h. This header file contains is what declares the method that is actually used to get the sensor data. When I run ./read, the compiled executable from the files above, I get the following output:

$ sudo ./read
Library version = 0x10408
Opening port 0
FT_Open succeeded.  Handle is 0x1f24930
FT_GetDeviceInfo succeeded.  Device is type 9.
FT_EE_Read succeeded.

Signature1 = 0
Signature2 = -1
Version = 0
VendorId = 0x0403
ProductId = 0x6015
Manufacturer = 
ManufacturerId = 
Description = 
SerialNumber = 
MaxPower = 90
PnP = 1
SelfPowered = 0
RemoteWakeup = 0
Returning 0

Which suggests that the USB port is active and can be read from. My issue is that having looked for sometime I can't find documentation or glean much meaning from the given files as to what all these values mean (for example: what does Device is type 9 mean?) and although there are more methods in the included in the header file, including a Read File method that should be able to read the stream from the ttyUSB* serial port, many of these are marked as Win32 (using windows.h and I am using Linux).

Essentially my question is: Are these the correct methods to be using for reading and writing from this sensor with my set-up? If yes, can you briefly describe how you would do this? If no, what should I be doing instead?

Apologies for the length of the question or if I have missed something obvious, my background is very much in software so working with this hardware is quite a mystery to me!

\$\endgroup\$
  • \$\begingroup\$ Did you check out ftdichip.com/Support/Knowledgebase/index.html?ft_read.htm ? For sending data you can use FT_Write. Accessing the eeprom is normally not required and only meant for changing certain settings of the device. Generally I would recommend to use the VCP driver instead of D2XX as it is easier to handle for many languages. But for C++ the D2XX is fine. \$\endgroup\$ – Christian B. Sep 23 '19 at 15:26
  • \$\begingroup\$ and the second example of ftdichip.com/Support/SoftwareExamples/CodeExamples/VC.htm should be quite helpful. \$\endgroup\$ – Christian B. Sep 23 '19 at 15:27
  • \$\begingroup\$ Thanks for the comments @ChristianB. ! The FT_Read and FT_Write methods you mentioned look to be what I am after. I am considering using VCP instead (both at your recommendation and to remove the need to call rmmod repeatedly on new set-ups), if I were to do this would I still be using the same read and write methods you referred to? Or are they driver specific methods? \$\endgroup\$ – madmissmolly Sep 23 '19 at 15:45
  • \$\begingroup\$ they are d2xx specific calls. With the VCP driver one can address the device as a general com port. For information regarding that topic looking for "access com port ubuntu c++" might be helpful or take a shortcut to stackoverflow.com/questions/18108932/… . \$\endgroup\$ – Christian B. Sep 23 '19 at 17:35
0
\$\begingroup\$

As Christian B says in the comments there is no need to use the D2XX driver.

You can just stick with the default virtual serial port provided by ftdi_sio and port Adafruit's python code to C or C++. That should be pretty easy with termios.

You can, of course, use that same python code as a reference and work with the D2XX driver but unless you are planning to be using this library a lot or you are working on a commercial product I doubt it would be worth the effort.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.