/* * SusConverter.cpp * * Created on: 17.01.2022 * Author: Timon Schwarz */ #include "SusConverter.h" #include #include #include #include //for atan2 #include bool SusConverter::checkSunSensorData(lp_vec_t susChannel) { if (susChannel.value[0] <= susChannelValueCheckLow || susChannel.value[0] > susChannelValueCheckHigh || susChannel.value[0] > susChannel.value[GNDREF]) { return false; } if (susChannel.value[1] <= susChannelValueCheckLow || susChannel.value[1] > susChannelValueCheckHigh || susChannel.value[1] > susChannel.value[GNDREF]) { return false; }; if (susChannel.value[2] <= susChannelValueCheckLow || susChannel.value[2] > susChannelValueCheckHigh || susChannel.value[2] > susChannel.value[GNDREF]) { return false; }; if (susChannel.value[3] <= susChannelValueCheckLow || susChannel.value[3] > susChannelValueCheckHigh || susChannel.value[3] > susChannel.value[GNDREF]) { return false; }; susChannelValueSum = 4 * susChannel.value[GNDREF] - (susChannel.value[0] + susChannel.value[1] + susChannel.value[2] + susChannel.value[3]); if ((susChannelValueSum < susChannelValueSumHigh) && (susChannelValueSum > susChannelValueSumLow)) { return false; }; return true; } void SusConverter::calcAngle(lp_vec_t susChannel) { float xout, yout; float s = 0.03; // s=[mm] gap between diodes uint8_t d = 5; // d=[mm] edge length of the quadratic aperture uint8_t h = 1; // h=[mm] distance between diodes and aperture int ch0, ch1, ch2, ch3; // Substract measurement values from GNDREF zero current threshold ch0 = susChannel.value[GNDREF] - susChannel.value[0]; ch1 = susChannel.value[GNDREF] - susChannel.value[1]; ch2 = susChannel.value[GNDREF] - susChannel.value[2]; ch3 = susChannel.value[GNDREF] - susChannel.value[3]; // Calculation of x and y xout = ((d - s) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm] yout = ((d - s) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm] // Calculation of the angles alphaBetaRaw[0] = atan2(xout, h) * (180 / M_PI); //[°] alphaBetaRaw[1] = atan2(yout, h) * (180 / M_PI); //[°] } void SusConverter::calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]) { uint8_t index; float k, l; // while loop iterates above all calibration cells to use the different calibration functions in // each cell k = 0; while (k < 3) { k++; l = 0; while (l < 3) { l++; // if-condition to check in which cell the data point has to be if ((alphaBetaRaw[0] > ((completeCellWidth * ((k - 1) / 3)) - halfCellWidth) && alphaBetaRaw[0] < ((completeCellWidth * (k / 3)) - halfCellWidth)) && (alphaBetaRaw[1] > ((completeCellWidth * ((l - 1) / 3)) - halfCellWidth) && alphaBetaRaw[1] < ((completeCellWidth * (l / 3)) - halfCellWidth))) { index = (3 * (k - 1) + l) - 1; // calculate the index of the datapoint for the right cell alphaBetaCalibrated[0] = coeffAlpha[index][0] + coeffAlpha[index][1] * alphaBetaRaw[0] + coeffAlpha[index][2] * alphaBetaRaw[1] + coeffAlpha[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] + coeffAlpha[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] + coeffAlpha[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] + coeffAlpha[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] + coeffAlpha[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] + coeffAlpha[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] + coeffAlpha[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°] alphaBetaCalibrated[1] = coeffBeta[index][0] + coeffBeta[index][1] * alphaBetaRaw[0] + coeffBeta[index][2] * alphaBetaRaw[1] + coeffBeta[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] + coeffBeta[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] + coeffBeta[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] + coeffBeta[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] + coeffBeta[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] + coeffBeta[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] + coeffBeta[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°] } } } } float* SusConverter::calculateSunVector() { // Calculate the normalized Sun Vector sunVectorBodyFrame[0] = (tan(alphaBetaCalibrated[0] * (M_PI / 180)) / (sqrt((powf(tan(alphaBetaCalibrated[0] * (M_PI / 180)), 2)) + powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1)))); sunVectorBodyFrame[1] = (tan(alphaBetaCalibrated[1] * (M_PI / 180)) / (sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) + powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1)))); sunVectorBodyFrame[2] = (-1 / (sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) + powf((tan(alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1)))); return sunVectorBodyFrame; } float* SusConverter::getSunVectorSensorFrame(lp_vec_t susChannel, const float coeffAlpha[9][10], const float coeffBeta[9][10]) { calcAngle(susChannel); calibration(coeffAlpha, coeffBeta); return calculateSunVector(); }