Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iMagic + Zwift | Powercalibration and -curve #30

Closed
WouterJD opened this issue Mar 3, 2020 · 53 comments
Closed

iMagic + Zwift | Powercalibration and -curve #30

WouterJD opened this issue Mar 3, 2020 · 53 comments

Comments

@WouterJD
Copy link
Owner

WouterJD commented Mar 3, 2020

IMagic + Zwift
image

PowerMeter + Garmin
image

Сurrent issues:

  1. The power coincides with some error, but it starts to differ greatly when the gradient changes.
  2. The brake force does not match the gradient. When riding horizontally or downhill, I ride as if constantly uphill.

From totalreverse wiki:

Range is 0x00...0xFF
0x80 is 'neutral' (electrical magnetic field switched off).
Values less than 0x80 reduce brake force (electrical magnetic field reduces the static magnetic fields) and values greater than 0x80 increase the brake force (electrical magnetic field increase the static magnetic fields).

But the value 0x80 does not match the gradient 0%. This is approximately a slope of 3-4%.
0x25 .. 0x35 = 0%.
This is all according to my feelings.

Originally posted by @yegorvin in #11 (comment)

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

Please refer to Resistance mode and The FortiusANT's powercurve as well as the comment in usbTrainer.py from line 185

Getting a good algorithm for a trainer (see Grade2Resistance() ) is the trick of a good trainer. Of course we want to believe all that the iFlow, iMagic and Fortius miss is the ANT-interface but the software in the trainer and the trainer itself have evolved as well.
Note that ALL that ZWIFT or TrainerRoad send to the trainer is TargetPower or Slope. It's up to the trainer to implement the behaviour.
Suggestions how to improve are welcome.

The Fortius is able to work with a negative power (driving the wheel when going down); does the iMagic do that as well?

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

The implementation of Resistance2Power() and Power2Resistance() has been done according the formula's as provided by GoldenCheetah and match the formula's used for Fortius.

I have seen TotalReverse's formula's but have chosen the current implementation; you might experiment here and I am curious for your experiences.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

Perhaps it's an idea to use ZWIFT in Erg-mode (where the training demands x Watt and the required power is sent to FortiusANT).
You can then check whether
a- ZWIFT-Required-Power is
b- displayed by FortiusANT (TargetPower=right meter left/bottom figure)
c- actually set by FortiusANT (Actual Power=right meter right/bottom figure) and
d- matches your power meter reading

This uses the technical code ZWIFT -> FortiusANT -> iMagic and back but eliminates the Grade2Resistance() code, which may be argued.

As soon as you are confident that the ERG-mode works, the basis is set and then the Grade-mode can be studied. I developed the software in this sequence (starting with Trainer Road and then ZWIFT) and also now it seems a good approach since the GradeMode uses the ERGmode.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

Note the conclusion on the powercurve page

@yegorvin
Copy link

yegorvin commented Mar 3, 2020

The Fortius is able to work with a negative power (driving the wheel when going down); does the iMagic do that as well?

No imagic can do this. But the rolling resistance is reduced to a minimum, even much less than the value when the brake is not connected to 220V power.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

In addition to other recommendations, you can also use the manual mode (-m flag) so you can set the power yourself.

@fritz-hh
Copy link
Contributor

fritz-hh commented Mar 3, 2020

Range is 0x00...0xFF
0x80 is 'neutral' (electrical magnetic field switched off).
Values less than 0x80 reduce brake force (electrical magnetic field reduces the static magnetic fields) and values greater than 0x80 increase the brake force (electrical magnetic field increase the static magnetic fields).

I saw this in the totalreverse wiki a few days ago too.
To me this explanatation in the wiki is not correct.
Especially 0x80 does not correspond to electrical field switched off.
From what I observed 0x00 = electrical field switch of,f and the resistance increases gradually wenn the value increases.
This is how it was implemented in FortiusANT, with the particularity that we never go below 0x30 (see:

rtn = int(max( 30, rtn)) # Minimum value
). I do not know why 30 is set as a minimum, but this is how GoldenCheetah does it.
This could explain why you always feel a resistance, even when going downhill.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

I have reviewed code again today, I'm pretty much convinced that the answer to the question must be found in Grade2Resistance()

@fritz-hh
Copy link
Contributor

fritz-hh commented Mar 3, 2020

I read the messages above too quikly...
That makes sense if the input from Swift were grades (and not power).

@yegorvin
Copy link

yegorvin commented Mar 3, 2020

From what I observed 0x00 = electrical field switch off

A value of 0x00 is much easier than just power off.
At 0x00, I can spin the wheel to a speed of 50+ km/h in the largest gear.
If you just turn off the brake from the 220V power supply, then even a speed of 30 km/h is difficult and I have to use a low gear.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

I read the messages above too quikly...
That makes sense if the input from Swift were grades (and not power).

Zwift can be either; grade when riding a track and power when doing a structured training

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 3, 2020

From what I observed 0x00 = electrical field switch off

A value of 0x00 is much easier than just power off.
At 0x00, I can spin the wheel to a speed of 50+ km/h in the largest gear.
If you just turn off the brake from the 220V power supply, then even a speed of 30 km/h is difficult and I have to use a low gear.

A suggestion for a test-case:

modify usbTrainer.py

def Power2Resistance()
....
    rtn = PowerInWatt
    return rtn

So the resistance that is set is always equal to the power required

modify FortiusANT.py

            if clv.manual:
                TargetMode = gui.mode_Power
                if   Buttons == usbTrainer.EnterButton:     pass
                elif Buttons == usbTrainer.DownButton:      TargetPower -= 10
                elif Buttons == usbTrainer.UpButton:        TargetPower += 10

So the required power is +/- 10 Watt (steps of 1 would be tedious to go from 0...250)

Start FortiusANT with the -m flag, so you set the required power with the Up/Down buttons.
Now you can manually set the resistance of your iMagic from the initial value of 100 and experiment what happens.

Calibration
Having the power meter at hand, you can make a calibration table (at 10 or 20 km/hr)

R =   0 S = 10 P = ?
R =  10 S = 10 P = ?
R = 250 S = 10 P = ?
R =   0 S = 20 P = ?
R =  10 S = 20 P = ?
R = 250 S = 20 P = ?

It will give insight in the behaviour of your equipment.
With a bit of luck: Power = (Resistance / a) + b) * Speed * c

Results
I have done similar tests and published here

@yegorvin
Copy link

yegorvin commented Mar 3, 2020

		      in prog	powermeter
R =   0 S = 10 P = 	25	34
R =  10 S = 10 P = 	28	39
R = 250 S = 10 P = 	131	94
R =   0 S = 20 P = 	48	88
R =  10 S = 20 P = 	58	90
R = 250 S = 20 P = 	260	230

Values at low speeds are large. error, it’s hard to provide such a low speed.

@totalreverse
Copy link

totalreverse commented Mar 3, 2020

When I write in the Wiki "0x80 is 'neutral' ", than I mean, that this is the default force of the eddy current brake in a static magnetic field.
You can pull the power plug out of your wall and you will have the same resistance as if you send a 0x80 to the trainer.

To reduce the the default ("neutral") resistance you have to actively compensate the static magnetic field with an electromagnetic field.
The firmware reduces the static magnetic field if you send values less than 0x80 to the head unit. A value of 0x7f results in a very small compensation. A value of 0x00 results in a full compensation. With values higher than 0x80, you add an additional electromagnetic field to the static magnetic field resulting in a higher resistance than the "neutral" resistance.

I did not deeply analyzed the Flow/iMagic trainers, but typically an electromagnetic field is "amplified" with a metal core, which has a saturation. So it doesn't make sense to further increase the electromagnetic field, if your metal core has achieved its saturation.

You may wanna have a look at this paper (page 59,60)
https://kluedo.ub.uni-kl.de/frontdoor/deliver/index/docId/1662/file/AmI_Bericht_Nr._5.pdf
There, a pulse length of 0.00 ms means "neutral" and they use pulse lengths from -4.2 to +4.2 ms.
Based on a power frequency of 50 Hz one sine has the length of 20ms: 10ms to increase and 10ms to decrease the static magnetic field. So they use only a small possible window to control the brake. Probably because the metal core is saturated after 4 to 5ms .
The Tacx firmware works fairly similar. The firmware (more or less) maps the values of 0x00...0x7f to a range of -5ms...0ms and the values of 0x81...0xff to 0ms...5ms (for 50Hz .. for 60Hz timing is scaled by 1/1.2)

@fritz-hh
Copy link
Contributor

fritz-hh commented Mar 3, 2020

@totalreverse : Thank you for the explanations.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

to provide such a low s

Please provide some more details on the test you performed.
At low speed, you need a high Resistance to achieve the TargetPower
Practice shows for the Fortius that the trainer does not perform well at low wheelspeeds, so try to keep high WheelSpeed and tune Resistance accordingly; of course Cadence can be as desired.

This may result that you ride at a certain Grade (uphill), Cadence and Power with a WheelSpeed of 30km/hr - but that is irrelevant. Zwift does not use your reported Speed but calculates the displayed speed using your Power (see here).

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

I watched the speed in the program.
Need data from Zwift?
Please indicate in more detail where to get each value in the experiment.
Thanks.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

Well...

If ZWIFT or TrainerRoad required 100Watt and ANT-message is sent to FortiusANT, the resistance is set and the Power is returned.

TargetPower     Resistance     CurrentPower
   100 Watt       xxxx               123 Watt
   100 Watt       yyyy               85 Watt
   100 Watt       zzzz               100 Watt

In the examples above xxxx is a too High resistance because the resulting power is higher than the requested power; yyyy is too low and zzzz is exactly right.

xxxx,yyyy,zzzz result from the formula's as described before

For calibration, please create such a table
As said, first do the test for 50/100/200/400 Watt (a range that suits your ability) keeping all other factors equal (gears and speed); to achieve higher power increase cadence.

And do the test for some sets of speed (10 kmh, 20 kmh, 30 kmh, 40 kmh).

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

TargetPower - in Zwift or in Fortius Antifier?
CurrentPower - from powermeter?
10 kmh, 20 kmh, 30 kmh, 40 kmh - speed in Zwift or in Fortius Antifier?

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

I would calibrate without Zwift, use the -m flag when starting FortiusANT so that you can set the TargetPower manually, using the headset.

The TargetPower and calculated Resistance are displayed by FortiusANT.

The CurrentPower and Speed are displayed by FortiusANT, resulting from your riding.
Use Speed to execute the test and ignore the CurrentPower for now (see last remark)

Use your powermeter to measure the real power.

This results in the table as suggested before

TargetPower     Resistance     PowerMeter
   100 Watt       xxxx               123 Watt
   100 Watt       yyyy               85 Watt                
   100 Watt       zzzz               100 Watt

I assume that the power returned by iMagic and displayed by FortiusANT matches the target-power. That must be the case as soon as the formula's are right.

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

I did just that and cited the results above.
Need more measurements at different speeds?
Please write in more detail since English is not my native language.

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

Having the power meter at hand, you can make a calibration table (at 10 or 20 km/hr)

For calibration, please create such a table
As said, first do the test for 50/100/200/400 Watt (a range that suits your ability) keeping all other factors equal (gears and speed); to achieve higher power increase cadence.

And do the test for some sets of speed (10 kmh, 20 kmh, 30 kmh, 40 kmh).

I'm confused :(

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

		      in prog	powermeter
R =   0 S = 10 P = 	25	34
R =  10 S = 10 P = 	28	39
R = 250 S = 10 P = 	131	94
R =   0 S = 20 P = 	48	88
R =  10 S = 20 P = 	58	90
R = 250 S = 20 P = 	260	230

Values at low speeds are large. error, it’s hard to provide such a low speed.

I understand that. Where are you from? Like to know just for curiosity.
I think you refer to the table as quoted.

Please describe some more:

  • what did you do / how did you set the target? manual power (-m), manual grade (-M), ZWIFT?
  • what is the "in prog" value

Most likely the test you did is OK, please describe how the test was executed.

I see your post (now above this one) and will write an instruction

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

Start FortiusANT with command "FortiusAnt.py -g -a -m"
The program will start at TargetPower = 100 Watt and allows you to set the TargetPower.

Push the down button, TargetPower will go to 50 Watt

Start cycling and maintain speed at 20km/hr
Write down Resistance and PowerMeter reading

Then push the UpButton to increment TargetPower to 100Watt and repeat
Then push the UpButton to increment TargetPower to 150Watt and repeat
Do this as far as you like it..

If done, a table as following is expected

TargetPower     Resistance     Speed     PowerMeter
      50 Watt          x       20 km/hr      xx
     100 Watt          x       20 km/hr      xx
     150 Watt          x       20 km/hr      xx
     200 Watt          x       20 km/hr      xx
     250 Watt          x       20 km/hr      xx

Succes! It's a pleasure doing the calibration with you :-)

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

PS. I expect Resistance to be a value between 30...226

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

I'm from Ukraine.

modify FortiusANT.py

            if clv.manual:
                TargetMode = gui.mode_Power
                if   Buttons == usbTrainer.EnterButton:     pass
                elif Buttons == usbTrainer.DownButton:      TargetPower -= 10
                elif Buttons == usbTrainer.UpButton:        TargetPower += 10

I did this and can change the load multiple of 10

modify usbTrainer.py

def Power2Resistance()
....
    rtn = PowerInWatt
    return rtn

I also did this action

Speed 20 km/hr - speed to watch in the Fortius Antifier?
image

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

Welcome Ukraine! Please "sign" the curiosity-page

Yes, looks good.
Like this you can modify the "TargetPower" in steps of 10Watt which directly sets the resistance to the selected value.

With this modification, the following table is expected

TargetPower     Resistance     Speed     PowerMeter
      10 Watt          10       20 km/hr      xx
      20 Watt          20       20 km/hr      xx
      30 Watt          30       20 km/hr      xx
      40 Watt          40       20 km/hr      xx
...
     250 Watt         250       20 km/hr      xx

Succes!

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

Thanks. Now in sufficient detail :)

Please "sign" the curiosity-page

I will give a report immediately when the system is used with your help.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

Top!

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

Is speed 20 km / h important?
Can I take measurements at a speed of 30 km / h?
Or maybe repeat the measurements for different speeds to build a 3D graph of the power curve.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

If you take more measurements, it gives a better view
10, 20, 30 would be enough I think

Good work, keep going!

@fritz-hh
Copy link
Contributor

fritz-hh commented Mar 4, 2020

Thanks a lot to you two for doing this calibration work! 😃

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

> 		      in prog	powermeter
> R =   0 S = 10 P = 	25	34
> R =  10 S = 10 P = 	28	39
> R = 250 S = 10 P = 	131	94
> R =   0 S = 20 P = 	48	88
> R =  10 S = 20 P = 	58	90
> R = 250 S = 20 P = 	260	230

I go back to this post.
I do not understand what the column under "in prog" means.

It cannot be the Resistance set in the trainer, because the max value is 0xff (one byte)

So please provide more details.

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

I do not understand what the column under "in prog" means.

This is the power in watts displayed in the Fortius Antifier.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

😀you wrote it😉

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 4, 2020

Don't worry, write a Test-description and a nice measurement table and then we go on. RIDE ON👍

@yegorvin
Copy link

yegorvin commented Mar 4, 2020

Res	10km/H	20km/H	30km/H	40km/H
10	32	85	140	190
20	32	85	140	190
30	32	85	140	190
40	32	89	140	190
50	32	89	140	210
60	34	93	150	
70	35	100	160	
80	38	105	170	
90	40	112	193	
100	42	128	210	310
110	48	139	230	
120	50	142	235	
130	50	145	245	
140	52	152	250	
150	58	162	265	~410
160	60	180	285	
170	65	190	310	
180	68	198	332	
190	70	207	340	
200	72	207	365	~550
210	72	210	370	
220	75	210	390	
230	75	210	390	
240	75	210	390	
250	75	210	390	

1 column - resistance in the Fortius Antifier.
2 .. 5 columns - power from powermeter for speed 10, 20, 30, 40 km/h

image

@yegorvin
Copy link

yegorvin commented Mar 5, 2020

PS. I expect Resistance to be a value between 30...226

Looking at the table the value is somewhere 40...220.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 5, 2020

I have seen the magnificent work you have performed yesterday and will study asap

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 6, 2020

Thanks again for the test; please evaluate Power calibrated with power meter (iMagic)

@yegorvin
Copy link

yegorvin commented Mar 6, 2020

Great job. I am glad that you have calculated a function that satisfies all the data from the test.
Check back soon.

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 6, 2020

The inverse functioneren is also needs; will see to find some time for that

@WouterJD
Copy link
Owner Author

WouterJD commented Mar 6, 2020

P2R and R2P both implemented. I'm curioous whether it works.
Succes!

@yegorvin
Copy link

yegorvin commented Mar 10, 2020

IMagic + Zwift
image
https://www.strava.com/activities/3172176238/analysis/26/391

PowerMeter + Garmin
image
https://www.strava.com/activities/3172175815/analysis/105/472

It is very similar, except for 300+ watts, there FortiusANT overstates by almost 100 watts.
See Strava activities.

I replaced the Tacx training tire with a wider one for roads, maybe the resistance constant has changed. Cadence in zwift is invalid because i did not connect the sensor.
Sorry, but I already opened the season on the street.

I watched the brake:
Now with Zwift:

Slope -5% - resistance on break 100 (somewhere such a load was on the plain)
Slope 0% - resistance on break 130 (twist hard for the plain)
Slope 5% - resistance on break 160 (for such a slope should be harder)

@WouterJD
Copy link
Owner Author

Reaction 1; the powercurve
A way to analyse the powercurve would be to export to .tcx (append /export_tcx to the strava link), import into excel, structure the data and feed into the formula's to check where the formula's go out of sync.

Overall not bad for the first 1:1 comparison iMagic/FortiusANT versus POwermeter :-)

@WouterJD
Copy link
Owner Author

Reaction 2; the powercurve.

The powercurve is the headache for simple developers as we are (we are not trainer-builder-specialists). Clearly Antifier struggled with it and so we do.
I have tried to be as transparent as possible using comment in the code and a wiki. Please study that, execute some experiments and let me know about your experiences.

Looking at your tests, I assume yur ftp will be above the default of 200Watt; so specify -f 312 (of course using your real ftp). The applied force is relative to this ftp.

The resistance uphill +20% is 150% of your ftp and the resistance downhill -20% is 100% of your ftp (at different cadences).
If you want to ride uphill at grade=+20% applying 250% and downhill at grade=-20% applying -100%, specify -r250/-100.

And if you do not like the idea of the powercurve as implemented but prefer formula 1,2 or 4, adjust the code where option=3 is the default, but 1,2,4 are permitted. Option4 is the most scientifical approach.

Succes! Now the real study begins: "How to build a realistic trainer for grade mode"!

@yegorvin
Copy link

The resistance uphill +20% is 150% of your ftp and the resistance downhill -20% is 100% of your ftp (at different cadences).
If you want to ride uphill at grade=+20% applying 250% and downhill at grade=-20% applying -100%, specify -r250/-100.

I can not understand the relationship between my ftp and break resistance at different slopes. In the Tacx Fortius program for each slope its own constant break resistance.

@WouterJD
Copy link
Owner Author

You are absolutely right; there should be no relation.
If you take your bike and go outside, ride uphill with +20% at 10km/hr the required effort is independant of your ftp.

Note two elements:
a. You would not ride uphill +20% because you can't, Zwift does present steep slopes
b. If you ride at low cadence in lowest gear your rearwheel will not slip, where your iMagic (my Fortius) does not perform well with high resistance at low wheelspeed.

Therefore additional measures need to be taken so that the trainer remains operational and within your limits. Indeed; this causes the Fortius to behave somewhat like an ergo-trainer and I'm convinced that this kind of challenges have brough Tacx to develop the direct-drive trainers.
Keep in mind: the software makes the iMagic listen to ANT but does not improve the behaviour of the trainer itself.

To study this subject, modify FortiusANT as follows
Set option =4 in the code (option = 3)

and add factor =1 before the code (Px = P * factor) so that the mathematic formula is unadjusted

Please let me know how that goes for you.
This should give a good starting point to further develop the algorithm.
I'm very curious for input from your side how this can be improved.

@yegorvin
Copy link

yegorvin commented Mar 12, 2020

https://www.strava.com/activities/1420773244/analysis
Here is my race with a big slope using Tacx Fortius program. Speed 10 km / h. And the wheel really spun very slowly and I used a very low gear.
Maybe everything that you write is valid only for your bike simulator?

In any case, with a slope of 0%, the resistance should be much lower.

@WouterJD
Copy link
Owner Author

May be, this is the advantage of open source: feel free to experiment.

@yegorvin
Copy link

Thank you, I will experiment.

@WouterJD
Copy link
Owner Author

Hi @yegorvin how are you?
I see that you are active on Zwift; what bicycle-gears and what settings do you use today and how is the "real" experience?

Curious to hear from you!

@WouterJD
Copy link
Owner Author

WouterJD commented Apr 6, 2020

@yegorvin traing and publishing on strava

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants