Data Field: AppBuilder

By user request, this app lets you define your own data field, based on a simple math formula like cadence / 2.

If you want to get fancy, there's conditional expressions (like IF in Excel), functions for data analysis (like MIN and AVG), and the data field can also display the text of your choice. The resulting data can be (optionally) written to the activity FIT file.

With AppBuilder, you can implement almost any field that involves math, such as: calculating normalized power and saving the data to the FIT activity file, showing the average pace for even-numbered laps, or recording the amount of time you sprinted.

Full documentation and examples here:
http://ciq-appbuilder.blogspot.com/

AppBuilder 5:
Now with new features! AppBuilder 5 is a completely new app, so please check it out in the store if you are interested in any of the new features.
https://apps.garmin.com/en-US/apps/fd690281-9c22-4fee-a81e-3b7f39aa67c5

- Store up to four formulas per app. Switch between formulas directly on the watch, without using a phone or PC. With four clone apps, you can store up to 16 formulas total
- User variables. Allows for powerful formulas where information can be stored at one point, like the start of a lap, and used later. e.g. Lap elevation change
- Improved timeavg() options. Allows for simpler, more flexible normalized power function
- More functions and variables

4 clones of AppBuilder are available in the store, so you can have 2 formulas in the same activity
  • Sorry for the extra post, but the forum wouldn't accept this text.

    FORMAT[X, formatString]
    - Formats a number freely

    e.g. 1 decimal place
    FORMAT[Speed, '.%1f']

    See:
    https://developer.garmin.com/downloads/connect-iq/monkey-c/doc/Toybox/Lang/Number.html#format-instance_method

    - Note: AppBuilder is unable to validate the format string or catch errors. Unfortunately, if the format string is incorrect, AppBuilder could crash, so please read the link above carefully.

  • Note: AppBuilder only recognizes straight single and double quotes for strings: ' "

    Curly smart quotes and apostrophes are not supported:‘ ’ “ ”

    Also, even though AppBuilder supports quotes, they won't work in Garmin Connect Mobile for iOS, because they'll be rejected from the settings. So it's better to use apostrophes.

    If you are getting the curly quotes when you type on your phone, hold down the apostrophe key until you see the pop-up with all the different kinds of apostrophes, and select the straight one.
  • hotdogpartysausage I did some searching and it looks like FTP is supposed to be based on average power, not normalized power.
    https://www.trainingpeaks.com/blog/functional-threshold-power-the-most-important-power-metric/

    First off, you could try this free FTP app I found in the store:
    https://apps.garmin.com/en-US/apps/a947db9d-abb6-4aea-818a-ee57fc369dbb

    Second, there is also a way to approximate the rolling average without storing all the data, using an exponential weighted average. It's not the same thing tho.
    https://stackoverflow.com/questions/12636613/how-to-calculate-moving-average-without-keeping-the-count-and-data-total
    double approxRollingAverage (double avg, double new_sample) {

    avg -= avg / N;
    avg += new_sample / N;

    return avg;
    }


    This can be done in AppBuilder. The general form would be:
    SETV(1, IF (GETV(1) eq NULL, 0, GETV(1) - GETV(1) / N + X / N))

    Where N is the number of samples and X is the quantity to sample.

    In this case, for 20-minute average power:
    SETV(1, IF (GETV(1) eq NULL, 0, GETV(1) - GETV(1) / 1200 + Power / 1200))

    And for FTP:
    SETV(1, IF (GETV(1) eq NULL, 0, GETV(1) - GETV(1) / 1200 + Power / 1200)) ; MAX(GETV(1)) * 0.95

    The thing with these formulas is they don't care if you've been riding continuously for a full 20 minutes (although the average will be smaller when the number of samples is less than 1200, and very small in the beginning). And the estimated average won't reset if you pause the timer. There are more complicated versions of this formula that would take pausing and the full window into account, but unfortunately they would need more memory than the F3 has.

    I sort of wish every Garmin had as much memory as the 645M or Fenix 5 Plus (as tiny as it is compared to any other modern device) -- so many more things would be possible.

    Please note you need to update AppBuilder for this to work -- I had an issue with certain devices like Fenix 3 where certain newly added functions were unavailable.
  • Thanks FlowState for taking the time to look into the equations for the power calculations and clarifying the use of avg power as opposed to NP for FTP calculations.

    I have tried the 'What's My FTP' datafield previously. Though I had a few instances where if I had a dropped powermeter signal for a few samples the datafield would crash so removed it. These issues may have been resolved so it might be worth trying again.

    I was doing a 45 recovery spin on the turbo tonight so quickly loaded the 20 min avg power equation into appbuilder on the fenix 3. This ride was at a pretty constant 110w. As you suggested the values reported by the datafield were initially small and slowly began to rise. However after 20 minutes the value was 70w as opposed to my 110w avg. The value continued to climb throughout the session peaking at 95w at the end of the 45min session. Would be this be the response you would be expecting?

    I do have an Edge 1030, which ultimately where I would use the datafield. All the app slots were currently taken on the edge so with the memory & functionality limitations in mind thought I'd try it on the fenix 3 first.
  • hotdogpartysausage no problem, I'm always looking for ways this app can be useful in some way.

    Well, it's not the same as the moving average -- newer values have a lot more weight than older values. I would expect the results to be different for sure. There's a whole discussion on that page about whether those approximations are any good -- TBH I haven't thought about it for long enough.

    Having said all of that, if you are on the Edge you have a ton of memory [8X as much as Fenix 3] and you have CIQ2 so you don't need some of the ridiculous workarounds in the CIQ1 formula.

    ( Sorry the formulas below need to have square brackets replaced with round brackets. I put them on pastebin in the correct format:
    https://pastebin.com/n1bMd39x )


    You should be able to use:
    MAX[TIMEAVG0[Power,1200,1]] * 0.95

    The 3rd parameter to TIMEAVG ["1"] specifies that an average won't be calculated until there are enough samples. In this case, you won't see anything until 20 minutes have passed.

    If you want the possibility to pause in the middle of the test without starting over, add "1" as the fourth parameter. This tells TIMEAVG to keep previous data while paused [but not collect any new data].
    MAX[TIMEAVG0[Power,1200,1, 1]] * 0.95

    You have enough memory to run that formula, the only thing I'm not sure about is whether there would be any performance issues related to adding up 1200 numbers once per second. [Yes I am aware that this may not be the best way to do things, but I really haven't tested with much more than a 5 minute window.] If you have chance, try it out and let me know. [

    If you want to see a countdown timer for the 20 minutes [and FTP afterwards]:

    - Reset on pause [I think this makes more sense for an FTP test]:
    ALT[MAX[TIMEAVG0[Power,1200,1] *0.95], FORMATTIME[MAX[if [PREV[timer] eq null, timer, null]] + 1200 - Timer]]

    - Don't reset on pause:
    ALT[MAX[TIMEAVG0[Power,1200,1, 1] *0.95], FORMATTIME[1200 - Timer]]

    For my part, I'll run the 20+ minute test in the simulator and see if it crashes. It won't run out of memory for sure, but I'm def not using the most efficient way to compute a rolling average with so many samples.

    In the end, it should be pretty easy to write a simple data field to do all this would even run on a Fenix 3. I wonder how many people want to see their estimated FTP during a ride if they have to wait 20 minutes, though. Do you get an estimated FTP when the ride is done, on the watch or cycling computer?
  • Update 5.4.7

    Optimize TIMEAVG so it isn't slower when you have lots of samples (e.g. over 1000 on newer Edge/Fenix 5+ devices), at the expense of making app a bit bigger. Only applies to CIQ2 devices, but older devices are not gonna be able to handle that many samples, anyway.

    (When I first coded AppBuilder, I didn't consider devices that had so much memory, or use cases where you would want averages for more than 1 to 5 minutes). I was pretty much focused on getting all the code to fit, at the expense of efficiency.)
  • hotdogpartysausage I realize now there's a problem with my approximate rolling average formula. If there's any nulls in the data (which could theoretically happen with power meter dropouts), it would reset the average (because arithmetic on null/blank results in null (*), while functions like AVG just ignore nulls.
    (* probably a huge mistake in my design...I should've just treated null like 0 in most cases, although I've seen it handled either way.)

    This would work better:

    SETV(1, IF (GETV(1) eq NULL, 0, GETV(1) - GETV(1) / N + ALT(X, 0) / N))
  • hotdogpartysausage I realize now there's a problem with my approximate rolling average formula. If there's any nulls in the data (which could theoretically happen with power meter dropouts), it would reset the average (because arithmetic on null/blank results in null (*), while functions like AVG just ignore nulls.
    (* probably a huge mistake in my design...I should've just treated null like 0 in most cases, although I've seen it handled either way.)


    Wow so many things to try it could be a busy weekend. Thank you

    I updated the datafield to the latest version on the fenix 3 this morning and loaded the revised equation. Replacing N with 1200 & X with Power however when I open the activity the screen just displays!Name
  • hotdogpartysausage I dunno, I think the field is way too complex for its own good, but no worries!

    Sorry, I forgot that ALT was only on CIQ2 devices. It's tiny and I managed find yet another way to optimize other code, so I added it for CIQ1.

    I would've expected you to see !AdvFn and not !Name, though. After updating, please copy the example directly from here (tap the copy icon):
    https://ciq-appbuilder.blogspot.com/p/examples.html#power_20_approx

  • Update 5.4.9

    - Add ALT() function for CIQ1 devices.

    ALT(X, Y)
    Returns X if X is not 0 and X is not NULL
    Otherwise returns Y

    - Optimize code to make app a bit smaller.