External Mesh Antenna Code error while using Workbench

When I run:

void selectExternalMeshAntenna() 



    digitalWrite(ANTSW1, 1);

    digitalWrite(ANTSW2, 0);


    digitalWrite(ANTSW1, 0);


    digitalWrite(ANTSW1, 0);

    digitalWrite(ANTSW2, 1);


In the Particle Workbench I get this error:

master2test.ino: In function 'void selectExternalMeshAntenna()':
master2test.ino:53:18: error: 'ANTSW1' was not 
declared in this scope
     digitalWrite(ANTSW1, 0);
master2test.ino:54:18: error: 'ANTSW2' was not 
declared in this scope
     digitalWrite(ANTSW2, 1);

However, when I run the same code in the Cloud IDE is runs without an issue. I’m just trying to flash the same code from the cloud IDE with my local Workbench.


What device are you targeting?
The #else branch also covers Gen1 & 2 devices which do not feature these pins.


reminder: we need this info to help troubleshoot :+1:

I’m using Gen 3 devices (Boron/Xenon), so do I just omit the else statement? However, when I run this the device range still doesn’t seem to increase significantly, I’m running SYSTEM_MODE(AUTOMATIC);. I currently put the antenna code before the setup function, should I put it inside the setup? Also is there any other code I need to include?

You might be using Boron/Xenon, but is Workbench actually targeting either of these?
Can you post a screenshot of the entire Workbench window?

I’d rather make it an #elif (PLATFORM_ID == PLATFORM_XENON) to avoid using any of these branches for Gen1&2.

Nope, this is a function which needs to be declared outside of any other function.
However, when this wasn’t clear, it may be worth mentioning that this function needs to be called in your code somewhere :wink:

There is a new feature in OS 1.5.0-rc.1


[Gen 3] Implements persistent antenna selection ( Mesh.selectAntenna() ) #1933

Should we be using the above, instead, for Gen 3 devices?

Also, combining the above info & the following post, I am guessing that we should not be referencing ANTSW1 = 0 , ANTSW2 = 0 any longer for Gen 3 devices.

@alanhao ANTSW1 = 0 , ANTSW2 = 0 is not a supported antenna switch configuration for any of Gen 3 platforms. With 1.3.1 you can simply do:

void setup() {
    // To select external antenna
    // To select internal antenna
1 Like

Thanks @ScruffR, I was able to get around the issue by just using the Cloud IDE, saved a lot of time.

Thanks @robc, in the last snippet of code you mentioned BLE, right now I’m using mesh for sensor data but encountering a lot of connection issues during field deployments when the devices are spaced further apart (even with a large mesh antenna devices will just disconnect after a while), I’ve tried everything including reloading bootloaders except for the first script you mentioned for external antennas in 1.5.0. Do you think BLE might be the better implementation for this situation (multiple xenon nodes ideally placed 100-300yd apart w/ external antenna with a boron for cloud transmission)? If so how much work would be involved to convert from mesh code to BLE mesh code? Can I still use Particle.publish() to push data to the cloud from a Boron?

@ScruffR Any thoughts?

Thanks again.

I apologize for not being clear and not getting back to you sooner. From what I gather, for your solution, I think you should try:


This is a new feature in the latest beta OS. Perhaps you should install this in your firmware for all of your Gen 3 devices. I am assuming you have already attached an external antenna (from Particle) on ALL your Gen 3 devices.

Having done this, next, make sure you have EACH device send a ping (Particle.publish()) periodically. Disconnections do occur and hopefully devices successfully reconnect. But, in your firmware, if you don’t detect a particular device reconnection after some time, you can manually attempt to force a reconnection. To reset a Xenon, it should already be mesh subscribed to receive a reset message from the Boron. If the Xenon is flashing green it may still receive this message and perform a System.reset within your Xenon handler.

You may need to reset the entire network. To do this, use a Particle.function() to respond to your command to reset the Boron first. Once the Boron is reconnected, then send messages to your Xenon’s to reset as above. Do this in sequence of nearest Xenon first, second nearest, third, etc. Nearest is based on distance or, if you know it, RSSI signal strength (I am still trying to figure out how to determine this RSSI signal strength of a Xenon).

You may also try a relay or repeater Xenon to see if that helps your network. By this I mean, if your distance between two particular Xenon’s may be too far, or, out of sight, try adding a device in-between to see if this helps cut down disconnections.

Also, there are posts about using Omni Directional antennas you can attach to your Boron and/or Xenon’s which will hopefully give you better range. I have not tried this.

I am sorry. I have no sound advice to offer on BLE. I am only guessing in what I said about it in my first post. I am hoping someone else can jump in and offer their help. Thanks!

@robc Thanks for the advice, I really appreciate it. I’ll implement this and see how it goes.

Hello, I know it’s been a while since the last post but I just got around to running some more tests.

I updated the device OS on my Boron and Xenon to the latest 1.5.0 rc2 pre-release, and I replaced my old mesh antenna code in setup with Mesh.selectAntenna(MeshAntennaType::EXTERNAL);

To test, I had a Xenon send out Particle.publish() messages every 5 sec and walked away from the Boron (main node) until event messages stopped showing up in the cloud. I then removed the mesh antenna code and tested again.

Result: I found no difference in range between using the built-in antenna and my external antenna. My antenna is a 1.5ft dual-band 5/4.5 dbi antenna so I would’ve expected a larger increase in range.

This leads me to believe that there’s an issue with external antenna connection/utilization.

Any suggestions?

Did you use Mesh.selectAntenna(MeshAntennaType::INTERNAL) for the other test?

With the old implementation the setting was not saved and reverted to INTERNAL if not set. However, with versions of Device OS that support Mesh.selectAntenna() the setting is saved in configuration flash and will stay at what it was previously set to.

I don’t see a range number in your post (I’m just curious). I would put the following code in the firmware of both devices while modifying the global to be the same in each device for each test:

bool g_externalAntenna = true;

void setup() {
  if (g_externalAntenna) {
  } else {

void loop() {


Also, because you are using SYSTEM_MODE(AUTOMATIC) with DeviceOS 1.5.0-rc.1 or 1.5.0-rc.2 , I would check out


in case any issues listed there are affecting your tests.

Many thanks to

Thanks for the suggestions @rickkas7 & @robc, I just tried the same range test but using the code which @robc provided, changing the bool to switch from internal/external antenna. But, I’m still getting the same range results as before, there seems to be no difference between the internal and external antenna.

This seems very odd, and I’m not sure if it’s a hardware or software issue. I checked out the suggested post and can’t find any issues there.

Any ideas? Thanks.

At this point, I would suggest following the advice of

Plenty of information will be needed from you to help resolve the [ISSUE]. Some of the information needed will be posting your code for both devices and describing the hardware configuration of each. You will need to specify what your results were compared to the results you expected. Please post your [ISSUE] soon so folks can have a chance to evaluate.

Ok, thanks again for your help @robc.