Я был озадачен публикацией, которая утверждала: можно измерить ваш FTP за минуту в Bikeradar. Далее Googling показал, что Baronbiosys.com разработал Xert-App , который утверждает это:
Метод использует сложные методы и распознавание шаблонов для определения вашего FTP. В то время как в прошлом вам либо нужно было тестировать, используя, например, 20 -минутный протокол FTP, либо изучить много месяцев данных, чтобы получить реалистичное значение FTP, этот метод позволяет вам определить ваш FTP в тот день или даже в тот момент. Ср. Баронбиозис
После установки приложения XERT на моем Garmin (830) я испытал, пока не будет затрачено бесплатное время пробного времени, что оно делает свои оценки FTP удивительно хорошо. Dcrainmaker рассмотрел его и довольно положительно относится к своей производительности и точности и пришел к выводу:
Принимая во внимание, что вот тот факт, что я получаю обратную связь FTP в режиме реального времени, что настолько уникально. Я могу выйти на прогулку и начать видеть, как эти значения формулируются, поскольку я прилагаю тяжелые усилия. Нет часов ожидания или даже через несколько минут. Я не знаю ни о какой другой платформе или приложении, который это делает. CF DCRAINMAKER
Я решил разработать код C ++ для закрытого учебного приложения, которая работает на экспресс -плате Arduino NRF52840, и это как можно ближе к функциональности приложения Xert (для Garmin Connect). Это стало неотъемлемой частью более крупного проекта: воздушный поток. Ниже приводится объяснение науки и математики за ее основами.
Мне было ясно, что приложение Xert основано на истощении так называемой анаэробной рабочей емкости ( AWC ) или функциональной резервной емкости ( FRC ). Чтобы сделать это просто, предположим, что у велосипедиста определенное количество этого конечная рабочая способность (энергетический запас), хранящийся внутри, в начале поездки. Это количество энергии известно в математических терминах как w ' (произносится w prime ), это энергия и, следовательно, измеряется в джоулях. В то время как вы едете с низкой интенсивностью, W ' остается на своем полном уровне, поскольку он не затрачен, и вы можете продолжать кататься на этой интенсивности в течение длительного времени. Но если вы нажимаете сильнее, вы начнете использовать эту энергию. Предел, с которого вы начнете тратить этот энергетический резерв, известен как критическая сила ( CP ). Если вы нажимаете на педали сильнее, чем CP , W ' уменьшится. Как только ваша производимая сила (ватты) становится ниже, чем CP , W ' будет «регенерировать», и энергетический резерв снова увеличится. Когда вы ездите достаточно долго ниже CP , W ' снова приблизится к уровню 100%. Однако, когда вы работаете усердно и достаточно долго над CP , W ' будет полностью истощен, и вы будете исчерпываются в тот самый момент (он же лим )! Различия в W ' выражаются как « W» баланс »в алгоритме доктора Скиба (2). Другим параметром алгоритма является тау , который определяет скорость, с которой w ' восстанавливается, когда мощность ниже CP .
CP определяется как самая высокая интенсивность упражнений, которая может поддерживаться в течение длительных периодов времени, обычно в течение от 45 до 60 минут. Функциональная пороговая мощность ( FTP ) более известна в рекреационном велосипеде и была определена как самая высокая средняя выходная мощность, которую можно поддерживать в течение 60 минут (1). Учитывая большое сходство в определении, мы предполагаем, что для неэлитного циклирования отсутствие значительного различия между значениями CP и FTP !
Алгоритмы, которые должны были быть реализованы, - это оригинальный алгоритм доктора Скиба (2) и оптимизация (приближение) интегрального алгоритма Skiba от Дейва Уотервора (3). Aart Goossens опубликовал код (в Python) и объяснительную информацию о GitHub (4), которая помогла многое понять и внедрить различные алгоритмы в обстановке Arduino. Следующая информация перефразируется из его первоначальной работы, чтобы дать читателю некоторое понимание в математическом фоне алгоритмов, см. Его работы по адресу: aart goosens @ github
Интегральный алгоритм Skiba является наиболее известным алгоритмом для расчета баланса W ' и был научно подтвержден (5). Уравнения для алгоритма: 
В тех случаях, когда W ' Bal (T) равен W' Bal в момент времени t , w ' - это количество доступной энергии выше CP (критическая сила), t , в течение которого рассчитывается W' BAL , итератор суммирования, w ' exp (u) количества энергии выше CP , который используется в момент времени U (потраченное), E -lecle Euler и ʈ w' (произносится на константу времени, которая описывает констант времени, которая описывает констант времени. Числа 546, -0,01 и 316 определяются экспериментально в оригинальной статье Скибы и не изменяются между людьми. D CP - это разница между CP и средней мощностью интервалов, в которых мощность была ниже CP . D cp может быть рассчитано динамически (среднее до времени t ) или рассчитывается один раз для всей тренировки и используется в качестве статического значения. Skiba рекомендует использовать статическое значение для D CP Полем P (t) - это мощность, производимая в момент времени t .
Математик Дейв Уотерворт (3) помог основному разработчику Золотого Гепарда Марка Ливерседж, разработать оптимизацию алгоритма Skiba (6). Эта переформулировка приближается к алгоритму Skiba, поэтому результаты могут немного различаться только в экстремальных случаях, особенно когда ( тау ) очень мало по сравнению со временем выборки. Интегральная часть уравнений Скибы переписана Waterworth в: 
Где s (t) является бегающей суммой в момент времени t после начала, другие символы соответствуют предыдущим уравнениям. Тау (ʈ w ' ) и w' exp (t) рассчитываются с исходными уравнениями, представленными Skiba. Интегральный алгоритм Skiba довольно дорогой в вычислении, даже на быстрых компьютерах, поскольку суммирование должно повторяться для каждого раз Т. Большим преимуществом оптимизации Waterworth является то, что теперь баланс может быть рассчитано в режиме реального времени: во время поездки и не только после этого! Кроме того, это очень полезно, когда кто -то хочет определить критическую силу на лету во время тренировок HIIT или напряженных тренировок, когда баланс W ' становится негативным и истощен!

Математически, отношение к продолжительности энергии описывается как гиперболическая функция. 4 различных точка на кривой представляют точки во времени ( T LIM ), когда достигается соответствующая максимальная устойчивая мощность выше CP , и происходит истощение. Когда учитывается толерантность к физическим упражнениям, власть-всимптота известна как CP (Watts). Константа кривизны известна как w ' (то есть w prime ), она измеряется в подразделениях выполненных работ (Joules). Обратите внимание, что 4 серого района, представляющие W ' , различаются по форме, но примерно равны по размеру. Эта гиперболическая взаимосвязь с продолжительностью энергии может быть преобразована в линейную взаимосвязь, если выполненная работа нанесена на построение времени, так что наклон линии равняется CP , а перехват равна w ' . Следует подчеркнуть, что отношения с продолжительностью власти описывают толерантность к физическим упражнениям, но не объясняют это. Тем не менее, физиологические реакции на физические упражнения, выполняемые ниже и выше CP, могут дать важную информацию о процессе усталости. CP первоначально определялся как внешняя выходная мощность, которая может быть поддержана «бесконечно» или в течение очень долгого времени без усталости. Однако это определение следует считать теоретическим, поскольку никакие упражнения никогда не могут быть выполнены на неопределенный срок. В настоящее время понятно, что CP отделяет выходы мощности, для которых допуск упражнений, как и ожидалось, ограничена (Phory Power> CP ). Фактическое время до непереносимости ( T LIM ) для упражнений, выполняемых выше CP, определяется и, следовательно, предсказано уравнением:
T lim = w ′/(p-cp)
Это уравнение подчеркивает, что время до непереносимости выше CP является функцией близости выходной мощности ( P ), поддерживаемой CP и размером W ' . Когда P значительно выше CP , постоянный объем работы, представленной параметром W ', будет быстро использоваться, а T LIM будет коротким. Если P будет ближе к CP , то W ' будет «использован» медленнее, а T LIM будет длиннее. Решающее внимание здесь заключается в том, что W ' считается постоянным для всех P выше CP . Таким образом, эта модель « два параметра » времени или продолжительности питания подразумевает, что абсолютная производительность упражнений зависит от простого значения CP (в ваттах) и значения W ' (в Joules). Параметры CP и W ' могут значительно различаться среди людей в зависимости от здоровья/заболевания, возраста, физической подготовки и обучения.
// ------------ W' Balance calculation -------------------
// Global variables related to Cycling Power and W-Prime
uint16_t TAWC_Mode = 1 ; // Track Anaerobic Capacity Depletion Mode == TRUE -> APPLY and SHOW
uint16_t CP60 = 160 ; // Your (estimate of) Critical Power, more or less the same as FTP
uint16_t eCP = CP60; // Algorithmic estimate of Critical Power during intense workout
uint16_t w_prime_usr = 7500 ; // Your (estimate of) W-prime or a base value
uint16_t ew_prime_mod = w_prime_usr; // First order estimate of W-prime modified during intense workout
uint16_t ew_prime_test = w_prime_usr; // 20-min-test algorithmic estimate (20 minute @ 5% above eCP) of W-prime for a given eCP!
long int w_prime_balance = 0 ; // Can be negative !!!
bool IsShowWprimeValuesDominant = false ; // Boolean that determines to show W Prime data on Oled or not
// ------------------------------------------------------- // ------------------------ W'Balance Functions -----------------------------------
uint16_t CalculateAveragePowerBelowCP ( uint16_t iPower, uint16_t iCP);
void CalculateAveragePowerAboveCP ( uint16_t iPower, uint16_t &iavPwr, unsigned long &iCpACp);
double tau_w_prime_balance ( uint16_t iPower, uint16_t iCP);
void w_prime_balance_waterworth ( uint16_t iPower, uint16_t iCP, uint16_t iw_prime);
void ConstrainW_PrimeValue ( uint16_t &iCP, uint16_t &iw_prime);
uint16_t GetCPfromTwoParameterAlgorithm ( uint16_t iav_Power, unsigned long iT_lim, uint16_t iw_prime);
uint16_t GetWPrimefromTwoParameterAlgorithm ( uint16_t iav_Power, double iT_lim, uint16_t iCP);
// ------------------------ W'Balance Functions ------------------------------------ uint16_t CalculateAveragePowerBelowCP ( uint16_t iPower, uint16_t iCP){
// calculate avg_power_below_cp real time using a running sum and counter
static unsigned long int CountPowerBelowCP = 0 ;
static unsigned long int SumPowerBelowCP = 0 ;
if (iPower < iCP) {
SumPowerBelowCP += ( unsigned long int )iPower;
CountPowerBelowCP++;
}
return uint16_t (SumPowerBelowCP/CountPowerBelowCP); // average power below CP
} // end calculate avg_power_below_cp
void CalculateAveragePowerAboveCP ( uint16_t iPower, uint16_t &iavPwr, unsigned long int &iCpACp){
// calculate avg_power_above_cp real time using a running sum and counter
// returning the values by C++ reference!
static unsigned long int SumPowerAboveCP = 0 ;
SumPowerAboveCP += ( unsigned long int )iPower;
iCpACp++;
iavPwr = uint16_t (SumPowerAboveCP/iCpACp); // average power above CP
} // end calculate avg_power_above_cp
double tau_w_prime_balance ( uint16_t iPower, uint16_t iCP){
uint16_t avg_power_below_cp = CalculateAveragePowerBelowCP (iPower, iCP);
double delta_cp = double (iCP - avg_power_below_cp);
return ( double ( 546.00 ) * exp (- 0.01 * delta_cp) + double ( 316.00 ));
} // end Tau W Prime Balance
void w_prime_balance_waterworth ( uint16_t iPower, uint16_t iCP, uint16_t iw_prime) {
// Most power meters measure power, torque a.o. in a high frequency (20-60 Hz) but
// transmit (BLE) datasets to a monitoring device in much lower frequency: 1-4 times per second.
int power_above_cp = 0 ; // Power > CP
static double T_lim = 0 ; // Time (duration) while Power is above CP, the summed value of every sample time value P > CP
double w_prime_expended = 0.0 ; // Expended energy in Joules
double ExpTerm1 = 0.0 , ExpTerm2 = 0.0 ;
static double TimeSpent = 0.0 ; // Total Time spent in the workout, the summed value of every sample time value
static double running_sum = 0.0 ;
static unsigned long int CountPowerAboveCP = 0 ; // Count the Power readings above CP
static uint16_t avPower = 0 ; // Average power above CP
const long int NextLevelStep = 1000 ; // Stepsize of the next level of w-prime modification --> 1000 Joules step
static long int NextUpdateLevel = 0 ; // The next level at which to update eCP, e_w_prime_mod and ew_prime_test
// Quarq Dfour Zero Spider power meter sends between 2 and 1.2 power readings per second, dependent of POWER level !!!
// We assume that the sample frequency (number of samples per second) is VARIABLE !!!
// Determine the individual sample time in seconds, it may/will vary during the workout !!!
static unsigned long PrevReadingTime = 0 ;
double SampleTime = double ( millis ()-PrevReadingTime)/ 1000 ; // Time or duration since the previous sample, convert from millis to seconds
PrevReadingTime = millis (); // Update for the next sample
double tau = tau_w_prime_balance (iPower, iCP); // Determine the value for tau
TimeSpent += SampleTime ; // The summed value of all sample time values during the workout
power_above_cp = (iPower - iCP);
# ifdef DEBUGAIR
Serial. printf ( " Time:%6.1f ST: %4.2f tau: %f " , TimeSpent, SampleTime , tau);
# endif
// w_prime is energy and measured in Joules = Watt*second
// Determine the expended energy above CP since the previous measurement (--> i.e. during sample time)
w_prime_expended = double ( max ( 0 , power_above_cp))*SampleTime; // Determine (Watts_above_CP) * (its duration in seconds) = expended energy in Joules!
// Calculate some terms of the equation
ExpTerm1 = exp (TimeSpent/tau); // Exponential term1
ExpTerm2 = exp (-TimeSpent/tau); // Exponential term2
# ifdef DEBUGAIR
Serial. printf ( " W prime expended: %3.0f exp-term1: %f exp-term2: %f " , w_prime_expended , ExpTerm1, ExpTerm2);
# endif
running_sum = running_sum + (w_prime_expended*ExpTerm1); // Determine the running sum
# ifdef DEBUGAIR
Serial. printf ( " Running Sum: %f " , running_sum);
# endif
w_prime_balance = ( long int )( ( double )iw_prime - (running_sum*ExpTerm2) ) ; // Determine w prime balance and cast from double to int
# ifdef DEBUGAIR
Serial. printf ( " w_prime_balance: %d " , w_prime_balance);
# endif
// --------------- extra --------------------------------------------------------------------------------------
// Workout starts at a certain W'= ##,### Joules and CP = ### watts, set by the user; the algorithm increases CP and W' stepwise
// to more realistic values every time when W'balance is depleted to a certain level; -> 2-Parameter Algorithm updates CP and W'
if (power_above_cp > 0 ) {
CalculateAveragePowerAboveCP (iPower, avPower, CountPowerAboveCP); // Average power above CP is to be calculated for future use
T_lim += SampleTime ; // Time to exhaustion: the accurate sum of every second spent above CP, calculated for future use
}
# ifdef DEBUGAIR
Serial. printf ( " [%d] n " , CountPowerAboveCP);
# endif
// When working above CP, the moment comes that we need to update eCP and ew_prime !!
if ( (w_prime_balance < NextUpdateLevel) && (w_prime_expended > 0 ) ) { // W' balance is further depleted --> test for an update moment
NextUpdateLevel -= NextLevelStep; // Move down another level of depletion, update eCP, ew_prime_mod and ew_prime_test
eCP = GetCPfromTwoParameterAlgorithm (avPower, T_lim, iw_prime); // Estimate a new eCP value
ew_prime_mod = w_prime_usr - NextUpdateLevel; // Adjust ew_prime_modified to the next level of depletion to be checked
ew_prime_test = GetWPrimefromTwoParameterAlgorithm ( uint16_t (eCP* 1.045 ), double ( 1200 ), eCP); // 20-Min-test estimate for W-Prime
# ifdef DEBUGAIR
Serial. printf ( " Update of eCP - ew_prime %5d - avPower: %3d - T-lim:%6.1f --> eCP: %3d " , ew_prime_mod, avPower, T_lim, eCP);
Serial. printf ( " --> Test estimate of W-Prime: %d n " , ew_prime_test );
# endif
}
// -----------------extra -------------------------------------------------------------------------------
} // end
// Check and Set starting value of w_prime to realistic numbers!!
void ConstrainW_PrimeValue ( uint16_t &iCP, uint16_t &iw_prime) {
if (iCP < 100 ) { iCP = 100 ; } // Update to lowest level that we allow for
// First determine the "minimal" value for W_Prime according to a 20-min-test estimate, given the iCP value!
uint16_t w_prime_estimate = GetWPrimefromTwoParameterAlgorithm ( uint16_t (iCP* 1.045 ), double ( 1200 ), iCP);
if (iw_prime < w_prime_estimate) { iw_prime = w_prime_estimate; } // Update iw_prime to a realistic level
return ;
} // end
uint16_t GetCPfromTwoParameterAlgorithm ( uint16_t iav_Power, double iT_lim, uint16_t iw_prime) {
uint16_t WprimeDivTlim = uint16_t ( double (iw_prime)/iT_lim ); // type cast for correct calculations
if (iav_Power > WprimeDivTlim){ // test for out of scope
return (iav_Power - WprimeDivTlim); // Solve 2-parameter algorithm to estimate CP
} else {
return eCP; // Something went wrong do'nt allow an update of CP
}
} // end
uint16_t GetWPrimefromTwoParameterAlgorithm ( uint16_t iav_Power, double iT_lim, uint16_t iCP) {
if (iav_Power > iCP){ // test for out of scope
return (iav_Power-iCP)*(( uint16_t )iT_lim); // Solve 2-parameter algorithm to estimate new W-Prime
} else {
return w_prime_usr; // Something went wrong don't allow an update of w_prime
}
} // end
Код был интегрирован в более крупный проект под названием Airflow . Установка или изменение базального CP и W Prime является неотъемлемой частью приложения Companion ! Умное устройство воздушного потока непрерывно настраивает запрошенную скорость воздушного потока охлаждающего вентилятора (ы) для стабильного теплового баланса во всех этапах тренировки в помещении, прогрева, интервалов интенсивности, прерывистого восстановления и при восстановлении. Велосипедист не имеет вмешательства на пути и может полностью сконцентрироваться на требованиях тренировки тренера Stationay, всегда обращаясь к идеальному воздушному потоку, который охлаждает его/ее соответствующим образом. Кроме того, велосипедисты получают (как бонусное) понимание в развитии его/ее критической силы , когда интенсивность тренировок интенсивна и достаточно длинная! Применяемый Arduino NRF52480 Express CPU настолько мощный, что расчет CP и W Prime может быть выполнена в стороне от всех расчетов для определения терминов теплового баланса и установления вентиляторов к соответствующей продувочной способности.
Велосипедист (свойства: CP = 140 Вт и W Prime = 7,2 кДж ) выполняет интенсивную тренировку с продолжительностью и интенсивностью, как показано на рисунке. W Prime истощается несколько раз во время первого интервального блока. Новые значения для CP и W Prime будут оценены алгоритмом во время тренировки только при необходимости. Запустите видео, чтобы увидеть 100% истощение W Prime и предполагаемые значения, как они были рассчитаны в режиме реального времени и представлены на OLED -экране ... Обратите внимание, как горизонтальная стержень сжимается, когда мощность выше CP в 175 и 195 Вт. Бар пропорциональна балансом W ', и, кроме того, что «осталось в баке», показано в процентах! Показания показаны в ускоренной последовательности и не соответствуют указанной продолжительности тренировки! 