Scales determineScaling(Function fun) { bool linear; bool sublinear; unsigned trial = 0; for (; trial < num_times; trial += 1) { if (trial > 0 && ((times[trial - 1] * sizes[trial]) > 10)) { break; } setA = &setsA[trial]; setB = &setsB[trial]; setAPrime = &setsAPrime[trial]; times[trial] = timeFunction(fun); printf("time taken for size %d was %g\n", sizes[trial], times[trial]); } if (trial < 3) { printf("I'm sorry, your program is way too inefficient.\n"); printf("you'll need to find a way-faster computer to test it on\n"); return SUPER_LINEAR; } linear = checkLinear(times, sizes, 0, trial - 1) || checkLinear(times, sizes, 1, trial - 1); sublinear = checkSubLinear(times, sizes, 0, trial - 1) || checkSubLinear(times, sizes, 1, trial - 1); if (sublinear) { return SUB_LINEAR; } else if (linear) { return LINEAR; } else { return SUPER_LINEAR; } }
/* * Step 5. Take MAX readings for 3 seconds then show results */ void ThrottleDetector::detectMaxCalibrate() { if ((millis() - startTime) < 2000 && sampleCount < maxSamples) { readThrottleValues(); } else { displayCalibratedValues(false); // take some stats before normalizing min/max int throttle1MinFluctuation = abs(throttle1MaxRest-throttle1MinRest); int throttle2MinFluctuation = abs(throttle2MaxRest-throttle2MinRest); int throttle1MaxFluctuation = abs(throttle1Max-throttle1Min); int throttle2MaxFluctuation = abs(throttle2Max-throttle2Min); // Determine throttle type based off min/max if (throttle1MinRest > throttle1Min+maxThrottleReadingDeviationPercent) { // high to low pot throttle1HighLow = true; } if (throttle2MinRest > throttle2Min+maxThrottleReadingDeviationPercent) { // high to low pot throttle2HighLow = true; } // restore the true min throttle1Min = throttle1MinRest; if ((throttle1HighLow && !throttle2HighLow) || (throttle2HighLow && !throttle1HighLow)) { throttle2Inverse = true; } // Detect grounded pin (always zero) or floating values which indicate no potentiometer provided if ((throttle2MinRest == 0 && throttle2MaxRest == 0 && throttle2Min == INT16_MAX && throttle2Max == 0) || (abs(throttle2MaxRest-throttle2Max) < maxThrottleReadingDeviationPercent && abs(throttle2MinRest-throttle2Min) < maxThrottleReadingDeviationPercent)) { potentiometerCount = 1; } else { potentiometerCount = 2; } // restore the true min/max for T2 if ( throttle2Inverse ) { throttle2Max = throttle2MaxRest; } else { throttle2Min = throttle2MinRest; } Logger::debug("Inverse: %s, throttle2Min: %d, throttle2Max: %d", (throttle2Inverse?"true":"false"), throttle2Min, throttle2Max); // fluctuation percentages - make sure not to divide by zero if (!(throttle1Max == throttle1Min)) { throttle1MinFluctuationPercent = throttle1MinFluctuation * 100 / abs(throttle1Max - throttle1Min); throttle1MaxFluctuationPercent = throttle1MaxFluctuation * 100 / abs(throttle1Max - throttle1Min); } else { throttle1MinFluctuationPercent = 0; throttle1MaxFluctuationPercent = 0; } if (!(throttle2Max == throttle2Min)) { throttle2MinFluctuationPercent = throttle2MinFluctuation * 100 / abs(throttle2Max - throttle2Min); throttle2MaxFluctuationPercent = throttle2MaxFluctuation * 100 / abs(throttle2Max - throttle2Min); } else { throttle2MinFluctuationPercent = 0; throttle2MaxFluctuationPercent = 0; } // Determine throttle subtype by examining the data sampled for (int i = 0; i < sampleCount; i++) { // normalize the values to a 0-1000 scale using the found min/max uint16_t value1 = normalize(throttle1Values[i], throttle1Min, throttle1Max, 0, 1000); uint16_t value2 = normalize(throttle2Values[i], throttle2Min, throttle2Max, 0, 1000); // see if they match known subtypes linearCount += checkLinear(value1, value2); inverseCount += checkInverse(value1, value2); //Logger::debug("T1: %d, T2: %d = NT1: %d, NT2: %d, L: %d, I: %d", throttle1Values[i], throttle2Values[i], value1, value2, linearCount, inverseCount); } throttleSubType = 0; if (potentiometerCount > 1) { // For dual pots, we trust the detection of >75% if ((linearCount * 100) / sampleCount > 75) { throttleSubType = 1; } else if ((inverseCount * 100) / sampleCount > 75) { throttleSubType = 2; } } else { // For single pots we use the high/low if (throttle1HighLow) { throttleSubType = 2; } else { throttleSubType = 1; } } char *type = "UNKNOWN"; if (throttleSubType == 1) { type = "Linear"; } else if (throttleSubType == 2) { type = "Inverse"; } if ( Logger::isDebug()) { Logger::console("\n----- RAW values ----"); for (int i = 0; i < sampleCount; i++) { Logger::console("T1: %d, T2: %d", throttle1Values[i], throttle2Values[i]); } } Logger::console("\n======================================="); Logger::console("Detection complete"); Logger::console("Num samples taken: %d", sampleCount); Logger::console("Num potentiometers found: %d", potentiometerCount); Logger::console("T1: %d to %d %s", (throttle1HighLow ? throttle1Max : throttle1Min), (throttle1HighLow ? throttle1Min : throttle1Max), (throttle1HighLow ? "HIGH-LOW" : "LOW-HIGH")); Logger::console("T1: rest fluctuation %d%%, full throttle fluctuation %d%%", throttle1MinFluctuationPercent, throttle1MaxFluctuationPercent); if (potentiometerCount > 1) { Logger::console("T2: %d to %d %s %s", (throttle2HighLow ? throttle2Max : throttle2Min), (throttle2HighLow ? throttle2Min : throttle2Max), (throttle2HighLow ? "HIGH-LOW" : "LOW-HIGH"), (throttle2Inverse ? " (Inverse of T1)" : "")); Logger::console("T2: rest fluctuation %d%%, full throttle fluctuation %d%%", throttle2MinFluctuationPercent, throttle2MaxFluctuationPercent); Logger::console("Num linear throttle matches: %d", linearCount); Logger::console("Num inverse throttle matches: %d", inverseCount); } Logger::console("Throttle type: %s", type); Logger::console("========================================"); // update the throttle's configuration (without storing it yet) config->minimumLevel1 = throttle1Min; config->maximumLevel1 = throttle1Max; config->numberPotMeters = potentiometerCount; if (config->numberPotMeters > 1) { config->minimumLevel2 = throttle2Min; config->maximumLevel2 = throttle2Max; } else { config->minimumLevel2 = 0; config->maximumLevel2 = 0; } config->throttleSubType = throttleSubType; // Done! state = DoNothing; TickHandler::getInstance()->detach(this); // send updates to ichip wifi DeviceManager::getInstance()->sendMessage(DEVICE_WIFI, ICHIP2128, MSG_CONFIG_CHANGE, NULL); } }