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
  • Is it possibile to use a function inside this PREVD function?
    PREVD(value, d)

    Like this?

    PREVD(value, lapdistance)

    ?
  • Great project! Congrats!

    i would like to create a formula for the slope of the current lap.
    i want (Altitude now - altitude at the beginning of the lap) / distance of the lap.

    Using the following, I think it is different. Because LapMin function takes the minimum value, not the first.
    (TotalAscent - LAPMIN(TotalAscent) - (TotalDescent - LAPMIN(TotalDescent)) / 1000 / lapdistance


    Well, TotalAscent and TotalDescent never decrease, so in this special case, the minimum lap value is equal to the value at the beginning of the lap..

    Is it possibile to use a function inside this PREVD function?
    PREVD(value, d)

    Like this?

    PREVD(value, lapdistance)

    PREVD and PREVT don't really work properly unless the 2nd parameter (t or d) is a constant, unfortunately. I think what you really want there is a general way to capture any value at the beginning of a lap, and unfortunately I don't have that for you.
  • for people interested, as Worstje I guess, I made an approximated version of the Minetti et al. (2002) formula to compute the running power. Their version use a 5th order polynomial of the altidtude gradient, which makes memory issue in AppBuilder. It seems that a second order polynomial is already very accurate to fit the curve in the paper, leading to a working formula in AppBuilder:
    the formula is
    P=weight x speed x (3.8188 + 17.58902 x gradient + 38.7 x gradient^2)

    this leadis to a working formula in AppBuilder in the form:
    XXX*timeavg(speed_raw,10)*timeavg((3.8188+((altitude_raw-prevt(altitude_raw,10))/(distance_raw-prevt(distance_raw,10)))*(17.58902+38.7*((altitude_raw-prevt(altitude_raw,10))/(distance_raw-prevt(distance_raw,10))))),10)

    In this implementation, you have to replace the XXX by your weight. Note that the value of speed is average over 10s, as well as a average value over 10 s of the Metabolic energy cost. The altitude gradient itself is computed with a 10 s PREVT function, but as already mentioned, a PREVD should be able to work also.
  • Any chance a functionality to add "last lap" information can be added? last lap HR is critical for me and cannot be displayed by Garmin devices.
  • Former Member
    Former Member over 6 years ago
    Just a question: I have a Fenix 5 and I'd like to view the "Distance to next waypoint" in nautical miles. Can Appbuilder help me on that?

    Many thanks!
    Giulio
  • Former Member
    Former Member over 6 years ago
    Is it possible to extract the current heartrate zone and plot it against time then have it written to the current activity FIT file?

    Fenix 5
  • zohare I don't have any plans to do so at the moment, but thank you for the suggestion!

    GiulioCanale Sorry, distance to next waypoint is not currently supported.

    RichardB The HR zone formula would be different depending on whether you want zones strictly as integers/whole numbers (e.g. 3), or with fractional decimals like Garmin Connect shows in the activity summary (e.g. 3.6).

    - Both formulas assume that the max physiologically possible HR is 220. (I've gone over my "normal" max HR in hot weather or when I've been out of shape).
    - Anything lower than zone 1 will be displayed as "0", and anything higher than HRMax will be displayed as "6"

    HR Zone (whole number)
    FINDLTEINDEX(HR+1, UserHRZone1Min, UserHRZone1Max, UserHRZone2Max, UserHRZone3Max, UserHRZone4Max, UserHRZone5Max+1, 220+1)


    HR Zone (decimal fraction)
    The generalized formula (I'm assuming) is: Fractional HR Zone = (Integer Zone) + (Heart Rate - Zone Min HR) / (Zone Max HR - Zone Min HR)
    (I've checked this against the zone numbers I've seen in Garmin Connect and the formula seems to match.)

    For AppBuilder:

    FINDLTEINDEX(HR+1, UserHRZone1Min, UserHRZone1Max, UserHRZone2Max, UserHRZone3Max, UserHRZone4Max, UserHRZone5Max+1, 220+1) + (HR - FINDGTE(HR, UserHRZone5Max+1, UserHRZone4Max, UserHRZone3Max, UserHRZone2Max, UserHRZone1Max, UserHRZone1Min, 35)) / (FINDLTE(HR+1, UserHRZone1Min, UserHRZone1Max, UserHRZone2Max, UserHRZone3Max, UserHRZone4Max, UserHRZone5Max+1, 220+1) - FINDGTE(HR, UserHRZone5Max+1, UserHRZone4Max, UserHRZone3Max, UserHRZone2Max, UserHRZone1Max, UserHRZone1Min, 35))

    Yep, it's long.

    HR Zone: Technical notes

    - Garmin supplies the following parameters for HR zones in the user profile: UserRestingHR, UserHRZone1Min, UserHRZone1Max, UserHRZone2Max, UserHRZone3Max, UserHRZone4Max, UserHRZone5Max

    Note that Zone 1 Max = Zone 2 Min, Zone 2 Max = Zone 3 Min, etc., so we have to make a judgment call on whether HR @ Zone 1 Max is in Zone 1 or Zone 2 (I think it should be in Zone 2). This ambiguity really only applies to the whole number formula, since any reasonable definition of the fractional HR zone will naturally have Zone 2 Max = 3.0.

    Zone 5 Max is the same as Max HR.

    - Why use 35 for the minimum heart rate in the fractional formula?
    Based on Garmin's native HR Zone field on the 935, it looks like Garmin uses a minimum HR of 35 for calculations.

    - Note that the more intuitive way to implement the "fractions" formula -- using IFS -- won't work because it causes a crash (in the simulator) for being too long and complicated. Of course, another way to simplify further would be to have local variables, but this is what we've got to work with now.

    - I should also apologize that the FINDLTE... functions are really unintuitive. Here's the explanation:

    FINDLTE(X, item1, item2, ...) finds the value of the first item where X is less than or equal to the item.
    FINDLTEINDEX(X, item1, item2, ...) finds the index (starting at 0) of the first item where X is less than or equal to the item.

    Questions you probably weren't going to ask:
    - Why use "HR+1" in FINDLTEINDEX(HR+1, ...)?
    Because I don't have a find less than (and not equal) function, and I want to find the correct integer zone (e.g. HR @ Zone 1 Max should be zone 2). In a perfect world I would just use FINDLTINDEX(HR, ...), if that function existed.

    - Why use "HR+1" in FINDLTE(HR+1)?
    For a similar reason to above: I want to avoid a situation where the algorithm calculates the same Zone Max HR and Min HR at the boundaries, and tries to divide by zero. (The use of both FINDLTE(HR) and FINDGTE(HR) would create that problem). In a perfect world, I would've just used FINDLT(HR, ...)

    - Why use "UserHRZone5Max+1"?
    Because I think HR @ Zone 5 Max (Max HR) is a special case where you should still be in zone 5, for the whole number formula. Due to the definition of the fractional formula, max HR will still show up as 6.0 in any case.
  • Former Member
    Former Member over 6 years ago
    Many thanks for that FlowState

    I finally got around to installing AppBuilder today and copy / pasted your formula into the settings for the app (1 field) and then added it as a custom data field to the run activity and had a wee pooter around my apartment to test it.

    When adding it as a custom field through the watch it come up with !name on the field and doesn't write the data to the FIT file though it is recognised on the FIT file.

    Link to activity: https://connect.garmin.com/modern/activity/3058504866

    Thoughts?
  • RichardB "!Name" is an error message which means that your formula had a name or symbol that AppBuilder doesn't understand.

    I tried both formulas on the device simulator without issues.

    I also tried both formulas on my 935, using Garmin Connect Mobile on an iPhone to send the settings to the app. I copied the formulas directly from the forum post and they both seem to work fine.

    Which formula are you using and how are you configuring the app?
  • Former Member
    Former Member over 6 years ago

    Apologies for the late reply - I've tried but have been getting the JSON errors for the last few days.

    I used the long formula but after changing to the shorter one it is working beautifully. Many thanks!

    One thought though. At the moment the chart is all blue. Is it possible to have the zone value match the colours that Garmin use