Convert accelerometer data from float to 16 bit integer

Hi!

I'm looking for some help in modifying code for a "headtracker", used to track your head movements to control RC drones. I need to get the data into the program SuperCollider, which takes 16 bit integer, while the code currently spits out floats.

I obviously want to keep as much precision in the data as possible, but I'm unsure how or where would be the best place in the code to intervene.

Here is the full code:
https://code.google.com/archive/p/open-headtracker/downloads

This is the function that outputs the values in the end:

void trackerOutput()
{
  Serial.print(tiltAngleLP - tiltStart + 90);
  Serial.print(",");
  Serial.print(rollAngleLP - rollStart + 90);
  Serial.print(",");  
  Serial.println(panAngleLP + 180);
}

And this is a function before it which calculates filters to smooth out the values:

//--------------------------------------------------------------------------------------
// Func: Filter
// Desc: Filters / merges sensor data. 
//--------------------------------------------------------------------------------------
void FilterSensorData()
{
    int temp = 0;

    // Used to set initial values. 
    if (resetValues == 1)
    {
#if FATSHARK_HT_MODULE
        digitalWrite(BUZZER, HIGH);
#endif
        resetValues = 0; 
      
        tiltStart = 0;
        panStart = 0;
        rollStart = 0;
  
        UpdateSensors();    
        GyroCalc();
        AccelCalc();
        MagCalc();
        
        panAngle = 0;
        tiltStart = accAngle[0];
        panStart = magAngle[2];
        rollStart = accAngle[1];

#if FATSHARK_HT_MODULE
        digitalWrite(BUZZER, LOW);
#endif
    }

    // Simple FilterSensorData, uses mainly gyro-data, but uses accelerometer to compensate for drift
    rollAngle = (rollAngle + ((gyroRaw[0] - gyroOff[0]) * cos((tiltAngle - 90) / 57.3) + (gyroRaw[2] - gyroOff[2]) * sin((tiltAngle - 90) / 57.3)) / (SAMPLERATE * SCALING_FACTOR)) * gyroWeightTiltRoll + accAngle[1] * (1 - gyroWeightTiltRoll);
    tiltAngle = (tiltAngle + ((gyroRaw[1] - gyroOff[1]) * cos((rollAngle - 90) / 57.3) + (gyroRaw[2] - gyroOff[2]) * sin((rollAngle - 90) / 57.3) * -1) / (SAMPLERATE * SCALING_FACTOR)) * gyroWeightTiltRoll + accAngle[0] * (1 - gyroWeightTiltRoll);
    panAngle  = (panAngle + ((gyroRaw[2] - gyroOff[2]) * cos((tiltAngle - 90) / 57.3) + (((gyroRaw[0] - gyroOff[0]) * -1) * (sin((tiltAngle - 90) / 57.3)) ) + ( ((gyroRaw[1] - gyroOff[1]) * 1) * (sin((rollAngle - 90) / 57.3)))) / (SAMPLERATE * SCALING_FACTOR)) * GyroWeightPan + magAngle[2] * (1 - GyroWeightPan);

    if (TrackerStarted)
    {
        // All low-pass filters
        tiltAngleLP = tiltAngle * tiltRollBeta + (1 - tiltRollBeta) * lastTiltAngle;
        lastTiltAngle = tiltAngleLP;
  
        rollAngleLP = rollAngle * tiltRollBeta + (1 - tiltRollBeta) * lastRollAngle;
        lastRollAngle = rollAngleLP;

        panAngleLP = panAngle * panBeta + (1 - panBeta) * lastPanAngle;
        lastPanAngle = panAngleLP;

        float panAngleTemp = panAngleLP * panInverse * panFactor;
        if ( (panAngleTemp > -panMinPulse) && (panAngleTemp < panMaxPulse) )
        {
            temp = servoPanCenter + panAngleTemp;
            channel_value[htChannels[0]] = (int)temp;
        }    

        float tiltAngleTemp = (tiltAngleLP - tiltStart) * tiltInverse * tiltFactor;
        if ( (tiltAngleTemp > -tiltMinPulse) && (tiltAngleTemp < tiltMaxPulse) )
        {
            temp = servoTiltCenter + tiltAngleTemp;
            channel_value[htChannels[1]] = temp;
        }   

        float rollAngleTemp = (rollAngleLP - rollStart) * rollInverse * rollFactor;
        if ( (rollAngleTemp > -rollMinPulse) && (rollAngleTemp < rollMaxPulse) )
        {
            temp = servoRollCenter + rollAngleTemp;
            channel_value[htChannels[2]] = temp;
        }
    }
}

Not looking at your code. But it sounds like the best place is just before you send it to SuperCollider if you want yo keep as much precision as possible in the Arduino code.

gorgon:
Hi!

I'm looking for some help in modifying code for a "headtracker", used to track your head movements to control RC drones. I need to get the data into the program SuperCollider, which takes 16 bit integer, while the code currently spits out floats.

I obviously want to keep as much precision in the data as possible, but I'm unsure how or where would be the best place in the code to intervene.

Do this:

integer = (float + 0.5);

This will give you the best possible conversion from float to integer.

Krupski:
Do this:

integer = (float + 0.5);

This will give you the best possible conversion from float to integer.

I went with a different solution. The way you suggested will loose a lot of data.

Essentially this is what I ended up with:

unsigned int x = (xAxisFloat + 10.0) * (65535 / 20.0); //scale float -10.0 to 10.0 to 0-65535 (16bit integer)

Which in my code looks like this:

  tiltFinal= (tiltAngleLP - tiltStart + 90) * (65535 / 360.0);
  rollFinal = (rollAngleLP - rollStart + 90) * (65535 / 180.0);
  panFinal = (panAngleLP + 180) * (65535 / 360.0);
  Serial.write(251);
  Serial.write(252);
  Serial.write(253);
  Serial.write(254);
  Serial.write(tiltFinal >> 8); //high 8bits
  Serial.write(tiltFinal & 255);  //low 8bits
  Serial.write(rollFinal >> 8);
  Serial.write(rollFinal & 255);
  Serial.write(panFinal >> 8);
  Serial.write(panFinal & 255);
  Serial.write(255);