ESP32c6: Enable external antenna on ESP AT Firmware

Hi All

I’m running the ESP AT firmware on the XIAO ESP32C6 board. How can I set it to use external antenna? I know Pin 3 needs to be set LOW and Pin 14 HIGH. But I’m trying to find a way to do this from AT firmware.

From looking at AT command list, there is a command to set register values (AT+SYSREG). In theory this should work (note the register 0x803 and 0x805 are from TRM as ‘GPIO Output Enable’ and ‘GPIO Output Value’ respectively):

AT+SYSREG=1,0x803,0x4008  // Set GPIO3 and GPIO14 as outputs
AT+SYSREG=1,0x805,0x4000  // Set GPIO3 low and GPIO14 high

However it doesn’t respond with OK and simply responds with “ready” (maybe its crashing and rebooting?)

I tried to test this by setting GPIO15 (LED) to high with

AT+SYSREG=1,0x803,0x8000  // Set GPIO15 output
AT+SYSREG=1,0x805,0x8000  // Set GPIO15 high

However this is not working…(no light)…can anyone help?

Hi there,
So I see the syntax looks good,
Based on the G man,
" The AT command to set register values is “AT+SYSREG”; it allows you to read or write values to specific system registers within a device, typically used in embedded systems like ESP32 modules where you need to access low-level hardware settings.

Key points about AT+SYSREG:

  • Function: Read or write values to system registers.
  • Syntax: AT+SYSREG=<direct>,<address>[,<write value>]
    • <direct>: “0” to read a register, “1” to write a register.
    • <address>: The address of the register you want to access.
    • <write value>: The value to write to the register (only used when writing).

Example usage:

  • Read the value of register at address 0x10: AT+SYSREG=0,0x10
  • Write the value “0x5A” to register at address 0x20: AT+SYSREG=1,0x20,0x5A "
 AT+RESTORE
OK
 ready

 AT+SYSREG=1,0x60009010,0x00001800  //Configure IO_MUX, drive strength, pull-up and pull-down mode of GPIO3
OK

AT+SYSREG=1,0x60004024,0x00000008  //Configure GPIO3 output mode 
OK

 AT+SYSREG=1,0x6000400C,0x00000008  //output low level
 OK

 AT+SYSREG=1,0x60004008,0x00000008  //output high level 
 OK

Try full values for the 32 bit registers PAGE 53 or the manual

3.1.27 AT+SYSREG: Read/Write the Register
Set Command
Command:
AT+SYSREG=<direct>,<address>[,<write value>]
Response:
+SYSREG:<read value> // Only in read mode
OK
Parameters
• <direct>: read or write register.
– 0: read register.
– 1: write register.
• <address>: (uint32) register address. You can refer to Technical Reference 
Manuals.
• <write value>: (uint32) write value (only in write mode).
Note
• AT does not check address. Make sure that the registers you are operating 
on are valid

HTH
GL :slight_smile: PJ :v:

your close you get it.

Many thanks for your help!

However I’m confused by your example…is this for C6 chip or maybe its for other?

According to ESP32C6 Technical Reference Manual. The address for IO_MUX is 6009_0000 (maybe that was typo?) but 6000_4000 register is listed for I2C not for GPIO.

I’m just trying to determine how you came up with those register numbers.

Maybe it would be easier if I tried to toggle onboard LED (Pin15?) because that would provide immediate feedback.

According to TRM it says:

7.5.3 Simple GPIO Output
GPIO matrix can also be used for simple GPIO output. For this case, one GPIO pin can be configured to directly
output the desired value, without routing any peripheral output to this pin. This can be done as below:
• Set GPIO matrix GPIO_FUNCn_OUT_SEL with a special peripheral index 128 (0x80);
• Set the corresponding bit in GPIO_OUT_REG register to the desired GPIO output value.

So GPIO_FUNC15_OUT_SEL should be offset of 0x554+(4*15) = 0x05A8
and GPIO_OUT_REG offset is 0x0004

Putting that all together this should work?? (But it does not toggle LED).

AT+SYSREG=1,0x600905A8,0x80 // Set GPIO_FUNC15_OUT_SEL with special index 128 (0x80)

OK

AT+SYSREG=1,0x60090004,0x8000 // Set GPIO_OUT_REG with 0x8000 (15th bit)

OK

…but no light

Replying to myself. Ok can set the LED on/off with:

AT+SYSREG=1,0x60091020,0x8001
AT+SYSREG=1,0x60091020,0x0001

Note: Keeping bit 1 set each time because GPIO1 is set as already for UART-TX

However, here is where things get odd. By default the XIAO running ESP Firmware seems to already use the external antenna? Booting with default firmware - not changing any registers - and scanning with AT+CWLAP indicates that its using external antenna by default (ie. drastic difference in reception when removing external antenna)

Is that a known thing?? Perhaps Seeed chose same setup as Espressif already used so ESP AT firmware by default enables external antenna? Any theories out there?

Hi u297c,

This is a sketch for blinking LEDs by register manipulation. Please refer to it.
ESP32C6_XIAO_REG_blink.zip (89.9 KB)

Also, the following link may be helpful regarding C6 RF switches.
XIAO_ESP32C6 Switching between builtin and external antenna - #16 by msfujino

1 Like

Thank you for this. Your blink-register sketch is particularly helpful.

I realize you are primarily working on Arduino framework related issues, but do you have any insight on the behavior I’m seeing booting the stock ESP AT firmware (GitHub - espressif/esp-at: AT application for ESP32/ESP32-C2/ESP32-C3/ESP32-C6/ESP8266)?

To my surprise it appears like the external antenna is enabled by default: RSSI Reception is dramatically better simply connecting the external antenna after a stock boot. Or could this just be that its still using internal antenna but RF leakage and mere presence of external antenna is “boosting” the internal antenna?

I’ve tried fiddling bits of Pin 3 & Pin 14 and I can’t see any real effect (but perhaps I’m just doing it wrong!). The only real noticeable effect I see is whether or not the external antenna is connected to UFL port…

To enable the external antenna, the RF switch must be powered (GPIO_3 = LOW).
It is unlikely that the AT firmware will turn on power to the RF switch, which is an XIAO_ESP32C6 specific function.

What would happen to the RSSI if I explicitly set GPIO_3 = LOW and GPIO_14 = HIGH?

I’ve done some tests and it seems to conclusively prove that the AT firmware is somehow booting with external antenna enabled.

This is shown by booting with no physical external antenna connected produces very bad reception BUT sending pin 14 low, and pin 3 high (ie. internal antenna config) drastically improves reception.

Likewise, simply booting with attached physical external antenna produces best reception. With physical antenna connected then “enabling it” via pin 14 high, pin 3 low produces no meaningful difference.

Fresh Boot No External Antenna

AT+CWLAP
+CWLAP:(3,“Kings24”,-61,“9c:a2:f4:76:69:48”,2,-1,-1,4,4,7,1)

OK

Fresh Boot With No External Antenna - First Setting Pin 3 High / Pin 14 Low / Pin 15 High (Only for LED) / Pin 1 High (UART TX). This is config for enabling internal antenna

AT+SYSREG=1,0x60091020,0x8009

OK
AT+CWLAP
+CWLAP:(3,“Kings24”,-38,“9c:a2:f4:76:69:48”,2,-1,-1,4,4,7,1)
+CWLAP:(3,“dhome24”,-79,“a0:04:60:1f:76:bb”,9,-1,-1,4,4,7,1)
+CWLAP:(3,"",-87,“be:d7:d4:61:50:29”,9,-1,-1,4,4,6,1)
+CWLAP:(3,“Tortos”,-90,“f4:17:b8:dd:b9:1f”,6,-1,-1,4,4,7,1)
+CWLAP:(3,“Tortos”,-92,“f4:17:b8:df:58:60”,11,-1,-1,4,4,7,1)

OK

Fresh Boot With External Antenna

AT+CWLAP
+CWLAP:(3,“Kings24”,-39,“9c:a2:f4:76:69:48”,2,-1,-1,4,4,7,1)
+CWLAP:(3,“dhome24”,-78,“a0:04:60:1f:76:bb”,9,-1,-1,4,4,7,1)
+CWLAP:(3,“Tortos”,-86,“f4:17:b8:dd:cf:13”,6,-1,-1,4,4,7,1)
+CWLAP:(3,“Tortos”,-87,“f4:17:b8:dd:b9:1f”,6,-1,-1,4,4,7,1)
+CWLAP:(0,“PN7FE0B2”,-92,“e8:31:cd:0b:40:a5”,1,-1,-1,0,0,7,0)
+CWLAP:(3,“Tortos”,-92,“f4:17:b8:df:58:60”,11,-1,-1,4,4,7,1)
+CWLAP:(3,“ATTrnKenRT”,-95,“a0:2d:13:b2:ec:ff”,11,-1,-1,4,4,7,1)
+CWLAP:(3,“S21 de Honi”,-96,“c6:6d:f5:14:fa:a6”,1,-1,-1,4,4,7,0)

OK

Fresh Boot With External Antenna - First Setting Pin 3 Low / Pin 14 High / Pin 15 High (Only for LED) / Pin 1 High (UART TX). This is config for enabling external antenna - No meaningful change!

AT+SYSREG=1,0x60091020,0xC001

OK
AT+CWLAP
+CWLAP:(3,“Kings24”,-39,“9c:a2:f4:76:69:48”,2,-1,-1,4,4,7,1)
+CWLAP:(3,“dhome24”,-80,“a0:04:60:1f:76:bb”,9,-1,-1,4,4,7,1)
+CWLAP:(3,“Tortos”,-85,“f4:17:b8:dd:cf:13”,6,-1,-1,4,4,7,1)
+CWLAP:(3,“Tortos”,-87,“f4:17:b8:dd:b9:1f”,6,-1,-1,4,4,7,1)
+CWLAP:(3,"",-88,“be:d7:d4:61:50:29”,9,-1,-1,4,4,6,1)
+CWLAP:(0,“PN7FE0B2”,-92,“e8:31:cd:0b:40:a5”,1,-1,-1,0,0,7,0)
+CWLAP:(3,“DIRECT-79-HP OfficeJet Pro 6970”,-92,“b0:0c:d1:fa:03:7a”,11,-1,-1,4,4,6,1)
+CWLAP:(3,“Tortos”,-94,“f4:17:b8:df:58:60”,11,-1,-1,4,4,7,1)
+CWLAP:(3,“Tortos”,-95,“dc:8d:8a:18:f9:a4”,6,-1,-1,4,4,7,1)

OK

the AT firmware is somehow booting with external antenna enabled

Even if the RF switch is not set correctly, the RF signal passes through a capacitance in the switch, so simply connecting an external antenna may give the appearance of increased sensitivity.

If the ESP AT has set the RF switch by default, you can check it by the value of the register.

AT+SYSREG=0,0x60091020 // read GPIO_ENABLE_REG

At least GPIO3 and GPIO14 bits are ‘1’ (e.g. 0x00004008)

AT+SYSREG=0,0x60091004 // read GPIO_OUT_REG

At least GPIO3 bit is ‘0’:power on and GPIO14 bit is ‘1’:external antenna (e.g. 0x00004000)

AT+SYSREG=0,0x60091020
+SYSREG:0x1
AT+SYSREG=0,0x60091004
+SYSREG:0x1

OK

On a fresh boot, only GPIO1 is set (I’m using GPIO0 and GPIO1 as UART interface therefore I assume GPIO1 is TX output).

Perhaps GPIO3 and GPIO14 are floating and thus not in any definite state.

The strongest point for me is if I boot with no physical antenna attached and then explicitly enable internal antenna (by setting 3 HIGH and 14 LOW) then reception dramatically improves.

Still a bit of a mystery of how its working…

GPIO_0 = HIGH: Initial value based on your information
GPIO_3 = LOW: Power is supplied to the RF switch
GPIO_14 = HIGH: Select external antenna
GPIO_15 = LOW: Turn on the LED

If you want to set the registers in the example of the above, try the following.
Please read “ESP32-C6 Technical Reference Manual” section carefully for more details.
7.5 Peripheral Output via GPIO Matrix
7.5.3 Simple GPIO Output
7.15.1 GPIO Matrix Register Summary
5.3.5 Modules/Peripherals Address Mapping

AT+SYSREG=1, 0x60091020, 0x0000C009 // enable GPIO0, 3, 14, 15
AT+SYSREG=0, 0x60091020 // check
 
AT+SYSREG=1, 0x60091004) = 0x00004001 // GPIO0=HIGH, 3=LOW, 14=HIGH, 15=LOW
AT+SYSREG=0, 0x60091020 // check

The following graph of my experiment shows how much sensitivity increase can be expected depending on the state of the RF switch and the presence or absence of the antenna.
XIAO_ESP32C6 Switching between builtin and external antenna - #16 by msfujino

edit
There was a mistake in the code, which has been corrected.

AT+SYSREG=1, 0x60091020, 0x0000C009 // enable GPIO0, 3, 14, 15
AT+SYSREG=0, 0x60091020 // check
 
AT+SYSREG=1, 0x60091004) = 0x00004001 // GPIO0=HIGH, 3=LOW, 14=HIGH, 15=LOW
AT+SYSREG=0, 0x60091004 // check
1 Like

Thank you. That is interesting.