Modifying CUL firmware to increase send limit for eq3 MAX! heating thermostats

MAX-HeizkoerperthermostatPlus-640040d2Updated November 2016 to completely remove credits handling so there is no restriction on transmission

I’ve recently purchased 10 of the eq3 MAX! central heating thermostats (TRV replacements) as well as 3 shutter contacts and 2 eco switches from conrad electronics. I also bought the MAX! cube but then decided to use a CUL device from to control them using FHEM because this allows for easier interaction with them and use of the eco switches directly.

ICUL_V3 soon discovered a problem in that when I tried to send a command to all of them (eg. set desired temperature) I very quickly “ran out of credit” with messages in the FHEM logs like “CUL_MAX_SendQueueHandler: Not enough credit! credit10ms is 2, but we need 115. Waiting 113 seconds” and I couldn’t do anything practical with them.

After reading this forum post (,17898.0.html) I decided to try to remove the send limit by recompiling the firmware.  Note that this means the CUL can now break the 1% transmission rule.

Update Firmware

  1. Download the firmware from here: (original:
  2. The code and firmware has been modified to make credit_10ms 900 all the time.  (If you wish to compile it yourself:
    cd Devices/CUL && make
  3. Flash the firmware on the device:
    1. Insert the CUL device with the microswitch depressed (lsusb reports 03eb:2ff4 Atmel Corp.)
    2. dfu-programmer atmega32u4 erase
      dfu-programmer atmega32u4 flash CUL_V3.hex
      dfu-programmer atmega32u4 reset
    3. Re-insert CUL device (lsbusb reports 03eb:204b Atmel Corp. LUFA USB to Serial Adapter Project)
  4.  A precompiled version with this change can be found here:

Stuck microswitch?

I’ve depressed the microswitch too many times so that it got stuck.  This means it’s always in bootloader mode.  To workaround this you can use a udev rule (disable it if you want to program the device!)”.

Add to /etc/udev/rules.d/99-usb-serial.rules (also adds a symlink to /dev/cul for the real device):

# CUL (LUFA USB to Serial Adapter Project)
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", RUN+="/usr/bin/dfu-programmer atmega32u4 reset"
SUBSYSTEM=="tty", ACTION=="add", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204b", SYMLINK+="cul"

Reload udev rules:

udevadm control --reload

26 thoughts on “Modifying CUL firmware to increase send limit for eq3 MAX! heating thermostats”

  1. Hi Matthew,
    thanks for your proposal to fix the Max! credit problem.
    I’m using a CUNO2 and I followed your instructions – unfortunately without success. Flashing was without any error. Now I get often the message “…disconnected, waiting to reappear…”
    Could you give me any hint?

  2. I presume that this did make a difference? I’m about to try some of these devices and I have a CUL already. I have heard about this sort of thing as causing trouble so would be great if this provided a solution.

    1. Yes I’m currently running a system with my modifications, 10 radiator valves, 7 Eco switches (as light switches) and a couple of door contacts. It works flawlessly

  3. Hi,

    thanks for this – it seems like this doesn’t solve the problem entirely, since you only modify the maximum burst length, so you can send 72 second bursts instead of 9 second bursts. If you have exhausted the 72 seconds, you have then used up the allowed airtime for 2 hours. It helps with sending initial configuration data, but if you run into the 1% rule during regular operation, you still have a problem…


      1. Thanks for this update, sounds like a winner!

        Can you give details of what changes you have made to the code to allow this, for future reference?



  4. Hi Matthew,

    great work!

    Would it be possible for you to provide the patch also for the Max cube? The device is supported for a while in a-culfw, but unfortunately, the cube part is missing in your builds.

    Best regards

  5. Hi Matthew,
    I discovered this site last night while trying to work out how to do exactly what you have already done. Serendipity!

    The only problem I have is that I am using a newish CUNX that relies on culfw v2.

    I am going to try and see what changes you have made and apply them to my copy of the v2 branch (locally).

    I would be grateful if you could point out any issues I might have doing this

    1. Just to let you know that I have successfully updated culfw v2 and loaded it onto my CUNX.
      Working perfectly.

      1. Hi Alan,

        Not being a programmer I have been unable to updat the culfw v2 for my CUNX. CUNX is so much more flexible than CUL so keen to use them as part of future expansion. Can you provide any guidance on exactly how to modify the V2 firmware for CUNX – I have enough expertise to do the flashing but not the coding/recompiling?



        1. Well you’ll need to edit the source code and recompile. Steps should be similar to the CUL I would think

        2. Hi Mike,
          I’m back home now.
          I guess your not interested in the source code changes so it’s probably best if I just let you have the compiled file – ready to flash.
          It’s here:

          Hope this helps.

          Note that I am no longer using my CUNX for MAX eq-3 as I had some weird behaviour.
          Instead I have reflashed my MAX Cube with the ARM version of culfw – also with credit checking turned off.
          However I was still getting a lot of bad data being returned and I have tracked it down to a piece of code in the firmware that seems to me to be completely wrong. If it was given a length byte for an eq-3 message that was too large it just read 29 bytes regardless and returned it – hence passinf rubbish back to fhem and also consuming potentioally vaild data that followed. So I changed that code in the ARM version and my system is now a lot more stable.


  6. hi, this cul-firmware was music in my ears 😉 so i flashed this cul-firmware…

    today morning one MAX-HeatingThermostat switched (it was set to ECO-Mode) to 12 degrees
    * eco temperature is 17 degrees and there is no setting in the temp with 12 degrees, i changed the window-open-temperature to 11.5 degrees a year ago…)
    * and some time later a Wall-Thermostat made first a “BOOST” and three minutes later it went to 22 degrees, it was in eco mode before, too…

    No “set … 12 degrees” or “set mode boost…” or “set desired-temperature 22” in my them.cfg, which has been unchanged regarding MAX/Heating-Settings for a while…

    no entry in the current fhem.log…

    I can’t believe this cul-firmware leads to transmission-errors which are understood by some random-max-devices setting wrong temperatures!?

  7. Hi Matthew,
    I made the CUNX changes locally to v2 of culfw
    I don’t know how to feed the changes back (and I don’t think the official culfw site would welcome them!)
    The ARM version changes I made to my Cube – to correct the over length handling ‘error’ were also made locally. I have not included them in the CUNX build as I have no way of testing it at the moment (as I am not using my CUNX).


    1. Yes, I was referring to the ARM version changes – be interesting to get the author’s feedback, and whether that is only an issue with the ARM version, or the CUL/CUN arduino versions as well.

      1. The length handling error exists in the mainline version and has just been ported to ARM.
        If I spoke German I would have raised the issue with the author.
        But it is working a lot better after my simple fix.

        1. Would you be able to share the fix that you did? I do speak some German and would like to test and get the changes upstream if appropriate.

          1. Hi Matthew,
            I changed two files: rf_moritz.h and rf_moritz.c.
            For the .h file I just added a new constant for minimum message length. I think that is actually 12 but, being cautious I set it to 10:
            #ifndef _RF_MORITZ_H
            #define _RF_MORITZ_H

            #define MAX_MORITZ_MSG 30
            #define MIN_MORITZ_MSG 10

            extern uint8_t moritz_on;

            void rf_moritz_init(void);
            void rf_moritz_task(void);
            void moritz_func(char *in);


            For the .c file I just changed some logic in rf_moritz_task in order to sanity check the length byte and return if it is out of range:

            //AGW** change validation to exit if too long or too short, rather than just limiting
            // max length
            if (enc[0]>=MAX_MORITZ_MSG || enc[0]<=MIN_MORITZ_MSG)
            // enc[0] = MAX_MORITZ_MSG-1; – this is original code
            This starts at line 221 in my copy.

            Hope this helps.


  8. Hi Matthew,

    i have the credit Problem. So i found your Page/github. But i have a nanoCUL, i build with Parts from the net. It seems that the Firmware of the naoCUL is not modified. Is it possible that you alter the nanoCUL firmware so i can use it on my diy CUL? Thanks for the great work!!


  9. Hi Matthew,
    is it possible to use your firmware on my diy nanoCUL? How can i modify the NanoCUL firmware?

Leave a Reply

Your email address will not be published. Required fields are marked *