Sensordaten über HidLib abfragen - Register des Sensors



  • Hallo,

    ich möchte eine Fehlerkorrektur für einen Lagesensor (Toradex: OakTilt, OpenSource unter http://developer.toradex.com/oak-sensors-and-interfaces) auszuwerten und die Daten fehlerzubereinigen.

    Unter http://www.c-plusplus.net/forum/315005 wurde mir bereits geholfen, auf unkomplizierte Weise über die OakLib die gelieferten Daten auszulesen. Hierzu gehören Frame (ein Zeitwert), Acceleration [m/s²], Azimuth [rad] und Zenith [rad].

    Nun habe ich im Datenblatt des Sensors gelesen, dass dieser auch einen Temperaturwert ausgeben kann, an welchem ich zur Fehlerkorrektur auch Interesse hätte.
    Allerdings wird dieser scheinbar nicht so komfortabel als "Channel" über die Libary ausgegeben, sondern soll laut Auskunft von Toradex direkt über die Sensorregister abrufbar sein.

    Im Datenblatt des OakTilt steht dazu folgendes:

    3.2.7
    Direct access to Sensor Registers
    
    This command allow to directly read and write registers of the sensor. This can be used for
    example to change the measurement mode (sensor bandwidth).
    Byte#
    Content
    GnS:
    0 1 2 3 4 5
    GnS 0x03 0x01 RegAddr 0x00 RegValue
    0 = Set
    1 = Get
    RegAddr: Register Address (refer to the SCA3000 datasheet for details)
    RegValue: Register content (refer to the SCA3000 datasheet for details)
    

    Im Datenblatt des verwendeten ICs hingegen wird nur der "temperature output" erwähnt, ohne spezifische Infos zu erwähnen.

    Die Datenblätter befinden sich für den OakTilt unter:
    http://docs.toradex.com/100095-oak-tilt-inclination-datasheet.pdf
    und für den eigentlichen Sensor unter:
    https://www.sparkfun.com/datasheets/Sensors/Accelerometer/SCA3000-D01.pdf

    Da ich neu auf dem Gebiet der Hardwareansteuerung bin, weiß ich nun jedoch nicht, wie ich an die Temperaturdaten des Sensors gelangen kann.

    Da ich unter Lubuntu 12.10 unterwegs bin und die Auswertung über die HidLib stattfindet, hoffe ich, dass mir in diesem Forum geholfen werden kann.

    Der Code zum Auslesen der Sensordaten sieht so aus:

    /// \file  
    /// \date 2008-10-10
    /// \author Xavier Michelon, Toradex SA 
    ///  
    /// \brief Sample program for using Oak device in Linux
    
    #include "OakHidBase.h"
    #include "OakFeatureReports.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string>
    #include <math.h>
    #include <unistd.h>
    #include <time.h>
    
    #define SAMPLEDELAY 0		// set report- und sample-rate - 20 works fine, choose as tiny as possible
    #define ARRAYSIZE 50		// size of array for arithmetic mean
    #define SLEEPVALUE 20000	// sleeptime between sensoraccess in µs - 25000 or even 2300 works fine...less need to be tested
    #define KORREKTURWERT 180.48	// value to set zero
    
    using namespace std;
    using namespace Toradex::Oak;
    int net = 0;			// total cycles
    int pet = 0;			// array position
    time_t now;			// get timestamp for logging purpose
    int channels;	// number of channels
    
    // Number of Samples
    long double messwerte[4][ARRAYSIZE]; // 0: Framenumber [s]	1: Acceleration [m/m²] 2: Zenith [grad] 3: Azimuth [grad]
    
    // define some local constants
    namespace {
       string const& kDefaultDevice("/dev/usb/hiddev0"); ///< Default device, if not specified as an argument
    }
    
    /// \brief wrapper function for error report that add file, line and function in which an error occured
    #define CHECK_OAK_CALL(status) checkOakCall(status, __FILE__, __LINE__, __FUNCTION__)
    
    //************************************************************************************************* 
    /// \brief Check the status code of a Oak library call. 
    ///
    /// If the status is not OK, this function display an error message to the standard error output
    /// then quit the application
    ///
    /// Note This function is not to be called directly, but via the CHECK_OAK_CALL macro that
    /// insert the line, file and function where the error occured
    ///
    /// \param[in] status the status code to check
    /// \param[in] file The file where the error occured
    /// \param[in] line The line number where the error occured
    /// \param[in] function The name of the function where the error occured
    //************************************************************************************************* 
    void checkOakCall(EOakStatus status, const char *file, int line, const char* function)
    {
       if (eOakStatusOK != status)
       {
          fprintf(stderr, "Error: %s in function %s (file %s, line %d)\n", getStatusString(status).c_str(), 
                  function, file, line);
          exit(1);
       }
    }
    
    				// compare function for sorting array
    int compfunction (const void * elem1, const void * elem2)
    {
    	if (*((long double*)elem1) > *((long double*)elem2)) return 1;
    	else if (*((long double*)elem1) < *((long double*)elem2)) return -1;
    	return 0;
    }
    
    //************************************************************************************************* 
    /// \brief The program entry point
    ///
    /// \param[in] argc The number of arguments of the program
    /// \param[in] argv The argument list of the program
    //************************************************************************************************* 
    int main(int argc, char **argv)
    {
      printf("\n \n \n");
      // if the device file is not provided as an argument, we use a default value
       std::string device(argc >= 2 ? argv[1] : kDefaultDevice);
    
       int deviceHandle;
       CHECK_OAK_CALL(openDevice(device, deviceHandle));
    
       // get the device informations
       DeviceInfo devInfo;
       CHECK_OAK_CALL(getDeviceInfo(deviceHandle, devInfo));
    
       // Set the report Mode
       CHECK_OAK_CALL(setReportMode(deviceHandle, eReportModeAfterSampling, true));
       EOakReportMode reportMode;
       CHECK_OAK_CALL(getReportMode(deviceHandle, reportMode, true));
    
       // Set the LED Mode
       CHECK_OAK_CALL(setLedMode(deviceHandle, eLedModeOff, true));
       EOakLedMode ledMode;
       CHECK_OAK_CALL(getLedMode(deviceHandle, ledMode, true));
    
       // Set the report rate
       CHECK_OAK_CALL(setReportRate(deviceHandle, SAMPLEDELAY, true));
       unsigned int reportRate;
       CHECK_OAK_CALL(getReportRate(deviceHandle, reportRate, true));
    //   printf("Report rate: %u\n", reportRate);
    
       // Set the sample rate
       CHECK_OAK_CALL(setSampleRate(deviceHandle, SAMPLEDELAY, true));
       unsigned int sampleRate;
       CHECK_OAK_CALL(getSampleRate(deviceHandle, sampleRate, true));
    //   printf("Sample rate: %u\n", sampleRate);
    
       // Retrieve Channel infos
       std::vector<ChannelInfo> channelInfos(devInfo.numberOfChannels);
       for (int i = 0; i < devInfo.numberOfChannels; i++)
       {
          ChannelInfo& chanInfo = channelInfos[i]; 
          CHECK_OAK_CALL(getChannelInfo(deviceHandle, i, chanInfo));
    //      printf("   Name: %s\n", chanInfo.channelName.c_str());
       }
    
      channels = devInfo.numberOfChannels;
    
    for (;;)			// read sensor data & save to array - endless loop
    {
    	usleep(SLEEPVALUE);
    	std::vector<int> values;
    	CHECK_OAK_CALL(readInterruptReport(deviceHandle, values));
    
    	const double mult2 = 180 / M_PI * pow(10.00, channelInfos[2].unitExponent);
    	const double mult3 = 180 / M_PI * pow(10.00, channelInfos[3].unitExponent);
    	messwerte[0][pet] = values[0];
    	messwerte[1][pet] = values[1];
    	messwerte[2][pet] = values[2] * mult2;
    	messwerte[3][pet] = values[3] * mult3;
    //	messwerte[4][pet] = // Logging der Temperatur - wie auslesen
    
    				// For analyzing realtime data remove uncomment lines
    //	printf("Ch0:\t%.2Lf\n", messwerte[0][pet]);	// frame
    //	printf("Ch1:\t%.2Lf\n", messwerte[1][pet]);	// acceleration
    //	printf("Ch2:\t%.2Lf\n", messwerte[2][pet]);	// zenith
    //	printf("Ch3:\t%.2Lf\n", messwerte[3][pet]-KORREKTURWERT);	// azimuth
    //	printf("Ch4:\t%.2Lf\n", messwerte[3][pet]);	// temp
    
    	++net;	// total cycles
    	pet=(pet+1) % ARRAYSIZE;	// array position
    }	// end of endless for-loop
    
    				// Cleanup
      CHECK_OAK_CALL(closeDevice(deviceHandle));
      return 0;
    }
    


  • So, in ner Skypesession mit nem Freund habe ich grade noch das Manual zum Sensor gefunden:

    http://labjack.com/sites/default/files/2011/06/SCA3000-Manual.pdf





  • Auf der Webseite des Sensor-IC-Herstellers hab ich noch was an PDFs gefunden.
    Unter anderem ein Code-Beispiel zum Auslesen eines Registers.

    http://www.muratamems.fi/en/support/obsolate-products/sca3000-series

    http://www.muratamems.fi/sites/default/files/uploads/tn55_c-code_example_for_sca3000_rev_0.1.pdf


Log in to reply