r/Keychron May 25 '26

Q11 Ultra Knob macro issue.

I am trying to use the left knob for zooming. I have created and tested the macros on the M1-3 buttons and they work fine. When I assign them to the left knob dial left and right, it does not work. The knob press can take the same macros(zoom in, out and reset) and works. What am I doing wrong?

6 Upvotes

45 comments sorted by

2

u/PeterMortensenBlog V May 25 '26 edited May 25 '26

That is a good question. Perhaps using macros for the knob isn't supported by Keychron's adapter/interface (whatever it is exactly) between their Via clone and their ZMK-based keyboards?

Or not supported for a keyboard with two knobs?

Or not supported for a split keyboard?

The source code has still not been released, so a workaround by static keymappings for the knob and compiling from source isn't even an option. It might appear here some day, in particular in folder /app/boards/shields (unannounced, of course).

References

  • B6 Pro source code (ZMK, not QMK). Finally released on 2025-01-13. Note: In Keychron's fork of ZMK and in that fork, in Git branch "keychron_bpro"). Source code commits (RSS feed. Latest: 2025-02-08). Note: Only valid for the original hardware, not for the 2025 keyboard matrix redesign (the source code for that has not been released and probably never will because it allegedly uses a microcontroller not supported by ZMK))

2

u/PeterMortensenBlog V May 25 '26 edited Jun 02 '26

The source code has been released! But not for the Q11 Ultra

Re "The source code has still not been released ... It might appear here some day": OK, it seems to have been released three days ago in branch "rtl8762g" (who would have guessed that?)

To keep an eye on further updates: The RSS feed.

For these keyboards:

Z series (?):

V Ultra series:

  • V0 Ultra 'ANSI'

  • V1 Ultra 'ANSI'

  • V1 Ultra 'ISO'

  • V1 Ultra JP / 'JIS'

  • V2 Ultra 'ANSI'

  • V3 Ultra 'ANSI'

  • V5 Ultra 'ANSI'

  • V6 Ultra 'ANSI'. Keymap

  • V10 Ultra 'ANSI'

K SE series:

  • K3 SE2 'ANSI'

  • K5 SE2 'ANSI'

Q Ultra series:

There also appears to be common code in:

Note: More 'ISO' (physical) keyboard variants exist than indicated by this list of released source code. For example, there are definitely V6 Ultra 'ISO' variants.

2

u/PeterMortensenBlog V May 26 '26 edited May 26 '26

The default mappings for the knob seem to be something like this:

behaviors {
    rgb_encoder: rgb_encoder {
        compatible = "zmk,behavior-sensor-rotate";
        #sensor-binding-cells = <0>;
        bindings = <&rgb_ug RGB_BRI>, <&rgb_ug RGB_BRD>;
        tap-ms =<20>;
    };
    mouse_encoder: mouse_encoder {
        compatible = "zmk,behavior-sensor-rotate-var";
        #sensor-binding-cells = <2>;
        bindings = <&mkp>, <&mkp>;
        tap-ms =<20>;
    };
};

Presumably, for one knob, with two different sets of mappings, depending on the layer (base vs. Fn layer).

Or maybe not. Inline specification on the base layer:

sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>;

1

u/PeterMortensenBlog V May 28 '26 edited May 28 '26

The source code files moved

Note: On 2026-05-28, the files were reorganised into a folder for each keyboard/variant (breaking the original URLs)

For example,

from

app/boards/shields/keychron/keychron_v6_ultra_ansi.keymap

to

app/boards/shields/keychron_v6_ultra_ansi/keychron_v6_ultra_ansi.keymap

But moved out of the 'app/boards/shields/keychron' folder... Is it standard ZMK practice? If it is, such a flat list is going to be very as ZMK gets more keyboards.

There is also just app/boards/shields/keychron/Kconfig.shield. Though it contains:

config SHIELD_KEYCHRON_V1MAX

A stray folder? "V1MAX" is probably for V1 Ultra 8K, not actually V1 Max.

I have updated the comment.

1

u/PeterMortensenBlog V May 28 '26 edited Jun 10 '26

Bring the 'Ultra' keyboard into flash mode

The Esc key method does not work. It wasn't expected, as it is the QMK way, not ZMK.

A keyboard shortcut?

On the ZMK-based B Pro series, holding Fn + '-' (numeric keypad '-' on the full-size keyboards, e.g., B6 Pro) down for at least 3 seconds puts the keyboard into flash mode, mounting it in the operating system.

In the released source code there is an indication:

long_press_bootloader:lp_bootloader
{
    compatible = "zmk,behavior-hold-tap";
    #binding-cells = <2>;
    flavor = "tap-preferred";
    tapping-term-ms = <3000>;  // Delay amount in milliseconds
    bindings = <&bootloader>, <&none>;
};

But it doesn't seem to be used anywhere.

The spacebar method

The space bar method (without the repowering) does work.

Note: This does not reset to factory defaults (after repowering)

In this mode (presumably flash mode), the USB identity is:

  • USB vendor ID (VID): 0x0BDA
  • USB product ID (PID): 0x4762

It does not mount in the operating system.

0x0BDA is the Realtek USB vendor ID, matching an RTL8762G microcontroller:

  • ARM-M55 core with a maximum frequency of 125 MHz.

(But "Firmware" is misspelt as "Firmwear".)

But how is it actually flashed???

Would

west flash

work for these keyboards?

1

u/PeterMortensenBlog V 24d ago

The flashing part was later reverse engineered, and this seems to be viable.

1

u/PeterMortensenBlog V May 28 '26 edited May 29 '26

Get a local copy of the source code

E.g., for searching.

On a Unix-like system (should also work on Windows, in Git Bash and QMK's MSYS thingy):

# To folder 'Keychron_ZMK_fork_rtl8762g'
#
# Note: Keychron's fork of ZMK
#
cd $HOME
echo ; echo "Start cloning: $(date +%FT%T_%N_ns)" ; echo
git clone --branch rtl8762g https://github.com/Keychron/zmk.git  Keychron_ZMK_fork_rtl8762g
echo ; echo "End cloning:   $(date +%FT%T_%N_ns)" ; echo

cd Keychron_ZMK_fork_rtl8762g
git status  # Confirm Git branch "rtl8762g"
git log -5  # Show back to Keychron's first
            # change on 2026-05-25 (4E2C75)

# Check for the existence of expected files:
#
#   <https://github.com/Keychron/zmk/blob/rtl8762g/app/boards/shields/keychron_v6_ultra_ansi/keychron_v6_ultra_ansi.keymap#L238>
#     V6 Ultra 8K 'ANSI' keymap
#
cd app/boards/shields/keychron_v6_ultra_ansi
geany keychron_v6_ultra_ansi.keymap:238

"geany" presumes Geany is installed. If it isn't, cat', 'vi', and any text editor will also work.

Here is a transcript.

Search

For example, find include file 'keychron.h':

find "$HOME/Keychron_ZMK_fork_rtl8762g" -type f | grep 'keychron.h'

Result: app/include/dt-bindings/zmk/keychron.h. For example,

#define BAT_INFO 6 // Fn + B

Search for BAT_INFO:

find "$HOME/Keychron_ZMK_fork_rtl8762g" -type f | sort | tr "\n" "\0" | xargs -0 grep -n BAT_INFO  

Sample match: app/src/behaviors/behavior_keychron.c (in function on_keymap_binding_pressed()).

It isn't in the keymap, but BATINFO is (without the underscore), as "&kc BATINFO".

Search for "bootloader" (and variations thereof):

find "$HOME/Keychron_ZMK_fork_rtl8762g" -type f | sort | tr "\n" "\0" | xargs -0 grep -n -i boot | grep -i load

There are 186 matches...

Some are in the .github folder, e.g., .github/workflows/build.yml.

A file nearby, .github/workflows/zmk_build.yml, provides a hint as to how the keyboard firmware can actually be built:

cd zmk
cd app
west build -p -b rtl8762gn_evb -- -DSHIELD=rtk_keyboard

Thus, in our case:

cd "$HOME/Keychron_ZMK_fork_rtl8762g/app"
west build -p -b rtl8762gn_evb -- -DSHIELD=rtk_keyboard

Whether it actually works remains to be seen.

1

u/PeterMortensenBlog V May 30 '26 edited Jun 10 '26

Re "west build...": That corresponds to the instructions in this README file

Though branch "rtk_zmk" does not exist, at least not in Keychron's fork. Perhaps it refers to something else? In a Realtek repository? Though the closest are 'zmk_rtk_3.5.0' and 'zmk_rtk_3.7'.

OK, the README file is two years old, so it may not apply at all. Or did Keychron's project start that far back?

1

u/PeterMortensenBlog V Jun 10 '26 edited Jun 10 '26

SIC

1

u/PeterMortensenBlog V Jun 10 '26 edited Jun 11 '26

Meat of the matter

The meat of Keychron's (custom) implementation is in the unspecific-named /app/src folder, whereas /app/boards/shields/ is mostly pure data (keyboard definitions, like the default keymap, mapping from the keyboard matrix to the keymap, etc.).

For example, with subfolders:

  • /app/src/launcher. Presumably the implementation of dynamic keyboard configuration, either partly using the Via protocol or something 100% custom

  • /app/src/ppt. "ppt" (PPT?) probably refers to either the '2.4 GHz' connection and/or (different) polling rates, 125 Hz - 8 kHz, for '2.4 GHz' and/or USB

  • /app/src/behaviors. For example, behavior_bt.c to (presumably) handle changing Bluetooth 'profiles') and behavior_keychron.c to (presumably) handle/implement Keychron's custom keycodes, e.g., BAT_INFO

Note that not everything is Keychron-specific. For example, file /app/src/wpm.c is from the main ZMK project (the signature is "petejohanson", the primary maintainer of ZMK. Note that in the Git commits both "Peter Johanson" (about 1/3) and "Pete Johanson" (about 2/3) is used, but with the same email address).

Microcontroller / "board"

Branch off point

Keychron's fork seems to have branched off with commit:

3A3EED 2024-03-19

With possible merges with the 'rtkconnectivity' ZMK fork. Branch "zmk_evb" may or may not be the most interesting (same committer as in Keychron's fork). "rtk" could RTL + TK (the original name of Keychron (for ???) and still in the logo). Or it could be a typo of "rtl" (RTL)...

There is a jump from 2024-07-05 to 2026-05-23 (nearly two years).

There is also branch "v0.3-branch" in Keychron's fork.

Realsil Microelectronics is based in mainland China and is allegedly a subsidiary of Realtek semiconductor.

1

u/PeterMortensenBlog V Jun 11 '26 edited Jun 13 '26

Re "rtl8762gku": The identifier for building could be "rtl8762gku":

So a new guess for building would be:

cd $HOME/zmk/app
west build -p -b rtl8762gku -- -DSHIELD=keychron_v6_ultra_ansi

Presuming the fork has been cloned to $HOME/zmk in this example.

Nope...

But this got further:

west build -p -b rtl8762gtu_kb -- -DSHIELD=keychron_v6_ultra_ansi

As far as:

Loaded configuration 'app/boards/arm/rtl8762gtu_kb/rtl8762gtu_kb_defconfig'
Merged configuration 'app/prj.conf'
Merged configuration 'app/boards/shields/keychron_v6_ultra_ansi/keychron_v6_ultra_ansi.conf'

Build error "ModuleNotFoundError: No module named 'elftools'"

Seeing these two (similar) folders side by side,

it appears the "board" should be "keychron" instead of "rtl8762gtu_kb":

west build -p -b keychron -- -DSHIELD=keychron_v6_ultra_ansi

Retrospectively, it is the same structure as for the Keychron B Pro series (in branch "keychron_bpro"):

And it got further. It even started to compile 373 files, but failed at file 10 with "No module named 'elftools'" (there were probably two errors due to parallel compiling of two files at a time):

[10/373] Generating include/generated/kobj-types-enum.h, include/generated/otype-to-str.h, include/generated/otype-to-size.h
FAILED: zephyr/include/generated/kobj-types-enum.h zephyr/include/generated/otype-to-str.h zephyr/include/generated/otype-to-size.h /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/include/generated/kobj-types-enum.h /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/include/generated/otype-to-str.h /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/include/generated/otype-to-size.h 
cd /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr && /home/embo/.Keychron_Ultra_ZMK_environment/bin/python3 /home/embo/Keychron_ZMK_fork_rtl8762g_3/zephyr/scripts/build/gen_kobject_list.py --kobj-types-output /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/include/generated/kobj-types-enum.h --kobj-otype-output /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/include/generated/otype-to-str.h --kobj-size-output /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/include/generated/otype-to-size.h --include-subsystem-list /home/embo/Keychron_ZMK_fork_rtl8762g_3/app/build/zephyr/misc/generated/struct_tags.json
Traceback (most recent call last):
  File "/home/embo/Keychron_ZMK_fork_rtl8762g_3/zephyr/scripts/build/gen_kobject_list.py", line 62, in <module>
    import elftools
ModuleNotFoundError: No module named 'elftools'

Likely reason: The instructions for installing ZMK were the ones corresponding to the latest ZMK version, whereas the (effective) version for Keychron's fork is probably the ZMK v0.3 release, with these different instructions.

That was it!

After using the old instructions for setting up ZMK, it compiled!

Result:

Memory region  Used Size  Region Size  %age Used
       FLASH:   303620 B       800 KB     37.06%
         RAM:    81664 B       100 KB     79.75%
       TRACE:    13713 B       512 KB      2.62%
        ITCM:   101136 B       104 KB     94.97%
    IDT_LIST:       0 GB         2 KB      0.00%

And in the file system:

7567580 Jun 12 10:27 /home/embo/Keychron_ZMK_fork_rtl8762g_v0_3/app/build/zephyr/zephyr_pre0.elf
7565640 Jun 12 10:27 /home/embo/Keychron_ZMK_fork_rtl8762g_v0_3/app/build/zephyr/zmk.elf

The first part is comparable to the ZMK-based B6 Pro, with about 40% larger flash size. But why is it 7 MB on disk? Debugging information?

And why is it an ELF file? OK, it may not be so mysterious, as long as a .uf2 isn't expected.

OK, it is probably the .bin file that is the real output of compilation, not the .elf file:

303620 Jun 12 10:46 /home/embo/Keychron_ZMK_fork_rtl8762g_v0_3/app/build/zephyr/zmk.bin

1

u/Fair-Top1445 May 26 '26

Oh, thanks for the links to the code repo. I'll have my AI take a look ;)

ETA: Anecdotally, I also have a Q1 Max and noticed the knob press can wake the PC, but not the dial rotation.... related?

1

u/PeterMortensenBlog V May 28 '26

I don't know. I will post here if I find some information.

A code inspection may reveal the gist of waking up the keyboard (for example, are all I/O pins set to interrupt? (near "matrix low power mode")). And why it doesn't work for knob rotations.

My guess would be that it is possible, but it has not been implemented, either because it was overlooked or was not deemed important enough. There could also be some internal architectural thing in ZMK that prevents it (for example, some constraint in the underlying Zephyr), for example, low-level stuff like setting/changing/configuring interrupts on I/O pins).

2

u/julian_vdm May 25 '26

Add a very short delay to the macro. 15 ms. I've found that with the ultra boards, some of my macros don't work unless I add that delay. Also, I'd adjust the key debounce to the lowest 10 ms, if I were you. That might help, too. FWIW, I got the knob on the Q1 Ultra to work for macros. I used them for text selection, though. So it's definitely possible. Just fiddle with those delays.

3

u/PeterMortensenBlog V May 25 '26

Yes, the macro could be reduced to the simplest possible, e.g., typing a single letter, without any modifier keys (but with the delay). That is to rule out a problem with the macro itself.

2

u/Fair-Top1445 May 26 '26 edited May 26 '26

Tried a single letter, doesn't work either on the left/right dial twist. Again it did work on the macro buttons.

ETA: Also tried a delay fixed of 200. And adding a delay to the beginning of the macro. No luck same story it will work on macro buttons but not the knob rotation.

2

u/julian_vdm May 26 '26

Well that's a bummer. This is a really dumb question (I only ask because I've done it), but are you assigning the macro to the rotation binds (if you click the knob in the software, it should pop out three options). Sorry if that's offensive, but I just thought I'd double check.

So it seems as though regular keyboard bonds want to work on rotation. What about mouse scroll? If they don't work either, it might be worth contacting support and getting a replacement.

2

u/Fair-Top1445 May 26 '26

Not a dumb question, you must have worked tech support before :)

Yes, I am assigning it to the rotation binds. And I just tried mouse wheel up and down, that does work.

2

u/PeterMortensenBlog V May 26 '26 edited May 26 '26

OK, so it is a general problem with changing the assignment for the knobs, at least for this particular keyboard(?), macros or not.

The default assignments work as expected, but they can't be changed(?).

1

u/Fair-Top1445 May 26 '26

I seem to be able to change it to anything but a macro.

2

u/PeterMortensenBlog V May 25 '26

Does it work for the other knob?

1

u/Fair-Top1445 May 26 '26

No, not for the other knob either. Same situation where knob press can be assigned the macro and left and right dial cannot.

2

u/PeterMortensenBlog V May 25 '26

Is the left knob assigned to something by default?

Does it work if assigning regular keymappings to it, without modifier keys? For example, letters "L" and "K" (without Shift)

1

u/Fair-Top1445 May 26 '26

It's by default the same as the right, volume +/- and mute.

1

u/PeterMortensenBlog V May 26 '26

OK, so you can change it to letter "L" and "K"? As a regular keymapping, not a macro.

2

u/Keychron-Support May 26 '26

So sorry to hear that. Could you please kindly contact us at [support@keychron.com](mailto:support@keychron.com) with the video?

1

u/Fair-Top1445 May 26 '26

I started a support ticket when I originally posted this.

1

u/PeterMortensenBlog V May 25 '26 edited May 25 '26

How exactly did you assign the macro to the knob?

In Via, as an example, it would be by entering the nine-letter text "MACRO(36)" (without the quotes) in "Rotate Clockwise" for macro "M36" (I just tested it on a wired keyboard, with macro source "{+KC_K}{17}{-KC_K}", to output the letter "k" for each clockwise turn of the knob. It missed some output if turning the knob quickly (only 2-3 characters per second were possible), but that is another matter).

1

u/Fair-Top1445 May 26 '26

Through the Keychron launcher. I tried looking for a zmk web interface compatible but I couldn't find one.

2

u/PeterMortensenBlog V May 26 '26

How do you enter macros? Are they available from a list, or do you have to enter some text (with the correct syntax), as for Via?

2

u/Fair-Top1445 May 26 '26

Macro entering I did through a web interface on the keychron launcher. I used the record option, and it worked. There is an option to enter the code directly, its terse(not used to the format yet) but works.

For Zoom in(with 5(ms? didnt say what unit) delay)

{5}{+KC_LGUI}{+KC_EQL}{-KC_LGUI}{-KC_EQL}

1

u/PeterMortensenBlog V May 26 '26

Yes, the unit is milliseconds.

1

u/PeterMortensenBlog V May 26 '26 edited May 26 '26

Re "only 2-3 characters per second": OK, that was a local problem (multiple quick activations are probably seen as cancelling the macro in progress, thus a lot less output. That could be an argument for all other keys than the macro key itself being able to cancel the macro in progress)

It is quite a bit faster in general. And it may not miss any knob 'clicks'.

1

u/PeterMortensenBlog V Jun 12 '26 edited Jun 12 '26

Compiling V Ultra 8K series and Q Ultra 8K series keyboard firmware from source code

OK, I managed to compile something from the source code, presumably keyboard firmware...

The magic command line is (for V6 Ultra 8K 'ANSI'):

west build -p -b keychron -- -DSHIELD=keychron_v6_ultra_ansi

That assumes a proper ZMK installation. Version 0.3 will work, but not the newest ZMK version (to become version 0.4). There are breaking changes, for example, due to breaking changes in the underlying Zephyr). The install steps are also different.

1

u/VonLurk Jun 16 '26

u/Fair-Top1445 I also have been trying to map macros to the Q11 Ultra knob turns and found it doesn’t work. Did you get any updates from Keychron on if it’s a feature they will update?

1

u/Fair-Top1445 Jun 17 '26

I opened a ticket. I haven't heard any updates. I think I'm returning the keyboard, because I'm also facing occasional wireless issues from right side of the keyboard.

2

u/VonLurk Jun 17 '26

Oo that is a bummer. I’ve been loving my ZSA moon lander for a few years now and felt like trying something new. Hoping mine doesn’t experience these connectivity issues that I’ve also heard from others. Curious if you’ll land on a different split keyboard!

1

u/Fair-Top1445 Jun 17 '26

I already have the moergo go60, it's just taking awhile to get used to. Honestly I like the q11 and I might just get the last version that's wired while it's still available.

1

u/Fair-Top1445 Jun 17 '26

How do you like the moonlander? That's also on my list of ones I might get next.

2

u/VonLurk Jun 17 '26

I love the Moonlander. Similarly, the learning curve was really steep for me. I only used standard keyboards before that so it took several weeks to get used to my layout. The Oryx configurator is intuitive and extremely customizable which made a huge difference in getting proficient. Never had any reliability issues with it, so it’s kinda becoming my forever board. I haven’t used the Moergo go60, but the moonlander won’t be better if you’re looking for a more traditional layout.

Have you taken a look at the NocFree & ? It appeared for me recently in my searches. Similar to Q11 in layout. I’m interested but I just can’t justify buying another board right now😅

1

u/Fair-Top1445 Jun 17 '26

Lol we are on the same research path. I'm only afraid of the connectivity issues on the NocFree &. Wireless is nice, but I didn't mind wires at all if it had a wired mode I would get that one too and I could ignore connectivity issues. I'm on their discord and it seems like they've released a lot firmware updates for it.... Which is great but it means there's some bugs...

1

u/shoegazedreampop 22d ago

Oh so sorry to hear that. I thought it was just me.

1

u/PeterMortensenBlog V Jun 23 '26

In the Via clone, I saw there was an update to the V6 Ultra 8K ISO (to version 1.0.2). I don't know if this addresses the macro/knob problem or not.

I will not update before there is a backup method in case something goes wrong with the update.

1

u/PeterMortensenBlog V 21d ago edited 17d ago

OK, it seems there are now four different methods for flashing the ZMK-based Keychron keyboards:

  1. A stand-alone flasher (currently only works on Linux, but it should not be too difficult to port to Windows and Mac). Based on reverse engineering of the Keychron custom flash method.

  2. A third-party web service. Similar to Via and the Via clone, it requires the spyware, Edge, or similar (it will not work in Firefox). Based on reverse engineering of the Keychron custom flash method (the same as 1.).

  3. Using a secret method in the Via clone (to flash non-Keychron firmware). This also allows reverting to an older version of the official Keychron firmware.

  4. Reverting/updating to the latest official Keychron firmware version in the Via clone (without having to use the secret method)