Viessmann vcontrold: 4 Years of Wrong Addresses and Too Much Cycling

While cleaning up my Grafana dashboards I noticed that my Viessmann Vitoladens 300-C cycles way too often: 17-52 burner starts per day, averaging just 9 minutes per run. That's way too short for an oil condensing boiler. So I dug deeper and found a massive bug in my vcontrold config in the process. Since 2022 I'd been reading and writing heating circuit 1 instead of heating circuit 2. All my heating curve changes went nowhere, all the logged values were phantom data.

I've been logging the heating system via vcontrold since 2019, and ever since the data has been flowing into InfluxDB so I can see in Grafana what the system is doing. Always worked, or so I thought.

How I found the bug

I changed the heating curve slope from 1.4 to 1.6 on the heating display as a test. vcontrold kept reading 1.2. That can't be right - either vcontrold is reading wrong or the display is showing garbage. So I checked the vito.xml: all the heating circuit commands were using 2xxx addresses (heating circuit 1). But my system only has heating circuit 2 with mixer M2. That one runs on 3xxx addresses.

My tests with a temporary config confirmed that the HK2 addresses deliver exactly the display values. The HK1 addresses showed frozen defaults. Since 2022 I'd been logging ghost data.

Viessmann Optolink address scheme

Heating circuits have different address ranges:

Heating circuit | Address range | Curve | Operation | Timer
HK1 (no mixer) | 2xxx | 27D3/27D4 | 2323 | 2000-2030
HK2 (with mixer) | 3xxx | 37D3/37D4 | 3323 | 3000-3030
HK3 (mixer M3) | 4xxx | same pattern | same pattern | same pattern

Global addresses (boiler, hot water, solar, burner) stay at 0xxx, 5xxx, 6xxx, 7xxx, 8xxx.

The big address correction

Moved all heating circuit commands from HK1 to HK2:

Command | Old (HK1) | New (HK2)
KennlinieNeigung | 27D3 | 37D3
KennlinieNiveau | 27D4 | 37D4
Betriebsart | 2323 | 3323
RaumNorSoll | 2306 | 3306
RaumRedSoll | 2307 | 3307
VLSoll | 2544 | 3544
Timer Mo-So | 2000-2030 | 3000-3030

On top of that I checked the OpenV reference XML and found even more broken addresses:

Sensor | Old | New | Problem
Speicherladepumpe | 6513 | 6513 | Stays correct (0845 was wrong, reverted)
Zirkulationspumpe | 6515 | 6515 | Stays correct (0846 was wrong, reverted)
Brennerstatus | 55DE | 0842 | Never showed ON
DrehzahlPumpeIntern | 7663 (CO) | 7663 (PC) | Unit correction

Sensors that constantly returned 20°C or ? I removed (WWAuslauf, RaumHK, Umschaltventil, BrennerStufe). The system doesn't have those sensors.

The cycling problem

With the correct addresses I could finally see real data. Analysis of the last few months:

Outside temp | Avg starts/day | Avg runtime/day | Avg min/start
-5° to 0° | 52 | 9.9h | 11.5 min
0° to 5° | 45 | 7.7h | 10.2 min
5° to 10° | 34 | 5.1h | 9.1 min
10° to 15° | 17 | 2.5h | 9.2 min

9 minutes per start is too short. Target for condensing operation: 20+ minutes. The live logs showed that during the shoulder season the cycling mainly comes from hot water heating, not from the heating circuit. The burner heats the boiler (55L volume) from ~48°C to 65-70°C for hot water, quickly reaches the cut-off hysteresis, and switches off. Then the next cycle starts.

Coding address 9F: the game changer

Research in Viessmann community threads turned up: coding address 9F controls the differential temperature between the boiler and the heating circuit with mixer. The factory value is 8K, so the boiler heats 8°C above the flow setpoint. At 9F=8 the mixer never opens all the way. The heat stays in the 55L boiler instead of flowing into the radiators.

So I set 9F to 0. That way the mixer is fully open at burner start, full flow runs through the radiators. The entire radiator and wall mass acts as a heat sink and the burner runs longer.

Experiences from the forum showed that this drops the starts by 22% (31->24/day) and increases the runtime by 21% (5.7->6.9 min).

Accessing coding level 2

Coding level 2 on the Vitotronic 200 display:

Menu + OK simultaneously for ~2 sec. -> coding level 1

Menu + OK simultaneously again -> coding level 2 (service)

Use up/down to pick the coding address -> OK -> change value -> OK

Groups: 00=scheme, 02-33=boiler, 55-75=hot water, 7F-95=general, A0-FF=heating circuit (9F lives here).

All changes from April 16, 2026

Setting | Before | After | Effect
9F (cod.2) | 8 | 0 | ~20% fewer starts
Curve slope | 1.4 | 1.0 | Lower flow temp
vcontrold addresses | HK1 (2xxx) | HK2 (3xxx) | Real values
Flame address | 55DE | 0842 | Burner status visible
Sampling | 3 min | 1 min | Capture cycling better

On top of that I lowered the heating curve slope from 1.4 to 1.0. Lower flow temperatures mean less oil and less aggressive cycling.

Outlook

Now I'm collecting 2-3 days of data with 9F=0 and slope 1.0. If the burner starts drop below 25/day and the runtimes climb above 12 minutes, it worked. In winter I'll then also test coding addresses C5, C6 and 06 to further limit the flow and boiler temperature.

The big lesson: always cross-check the display values against the logged values. Otherwise you spend 4 years optimizing ghost data.

[[img:1]]