PlatformIO.ini: pick upload port based on OS

Is there a way to have platformio detect the OS and select the upload port itself?

[env:uno]
platform = atmelavr
board = uno
framework = arduino
;upload_port = COM12
upload_port = /dev/ttyUSB2
lib_deps =
	Ethernet@^2.0.0
	PubSubClient

When I switch the operating system, Windows names upload_port as COMxx, while Linux calls it /dev/tty-something.

Can there be an if() statement in the .ini to let it figure it out itself?

For example:

[env:uno]
platform = atmelavr
board = uno
framework = arduino
if (OS==Windows10) {
  upload_port = COM12
} else {
  upload_port = /dev/ttyUSB2
}
lib_deps =
	Ethernet@^2.0.0
	PubSubClient

I don’t know if there is an if type construct, but depending on your platformio.ini construction use the global env to set all the shared configuration stuff, and have specific envs for the OS specific stuff, or you could extend environments… i.e. this is one I have open now that is dual-platform… uses the global env scoping that was introduced in PIO v4.0 to set up most of the board parameters, and the local envs to set up programmer / port specific stuff. The last env is there because I’m playing with the code inspection stuff coming in v4.1, and debug builds speed it up a bit.

[platformio]
description = Calibration routines for sensors

[env]
platform = atmelavr
framework = arduino
board = 328p8m
board_fuses.lfuse = 0xFF
board_fuses.hfuse = 0xDE
board_fuses.efuse = 0xFF
lib_deps = 
    54   ; DallasTemperature
    433  ; RF24
    1002 ; elapsedMillis
    1976 ; SerialCommands
monitor_speed = 9600

[env:Sensor-Serial-Windows]
upload_port = COM11
monitor_port = COM11

[env:Sensor-Serial-Linux]
upload_port = /dev/ttyUSB0
monitor_port = /dev/ttyUSB0

[env:Sensor-USBasp]
upload_protocol = usbasp
upload_flags =
    -Pusb
    -B0.5
upload_port = usb

[env:Sensor-USBasp-debug]
extends = env:Sensor-USBasp
build_type = debug

Another way to do it could be (the disadvantage being there would be the uno, uno-Windows and uno-Linux environments listed… the advantage being the uno env would still try to auto-detect ports):

[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps =
	Ethernet@^2.0.0
	PubSubClient

[env:uno-Windows]
extends=env:uno
upload_port = COM12

[env:uno-Linux]
extends=env:uno
upload_port = /dev/ttyUSB2

It would be nice if there was some way to do something like upload_port.win, upload_port.linux and upload_port.mac in order to do platform specific ports, making it more cross-platform friendly.

Whichever way you go… depending on your workflow, you may then want to use the default_envs parameter to set the build env that runs when you click on the global build task.

1 Like

First of all thank you for helping me out; much appreciated!

I added the above to the .ini

and get this error:

> Executing task in folder WaterLeakSensor: platformio run --target upload <

Warning! Ignore unknown configuration option `extends` in section [env:uno-Windows]
Warning! Ignore unknown configuration option `extends` in section [env:uno-Linux]

avrdude done.  Thank you.

================================================================= [SUCCESS] Took 10.61 seconds =================================================================

Processing uno-Windows ()
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Error: Please specify platform for 'uno-Windows' environment
The terminal process terminated with exit code: 1

Terminal will be reused by tasks, press any key to close it.

Initially I got 'install new udev-rules; which I did with:
https://docs.platformio.org/en/latest/faq.html#platformio-udev-rules

Still get the above error.

I did read the docs, but could not make sense of it. Your example makes sense, but it seems PIO does not know what to do with it.

I am on PIO 4.0.3

[Auto-detect put the firmware on USB0, not USB3; unless there is only one Arduino connected, the port needs to be specified.]

Ooops… I when back and checked the docs for extends … that’s a “New in version 4.1.” feature also! Sorry! :open_mouth:

So for now you’ll need to use the first form I showed… - the global env, with local envs for the win and linux serial bits. Should be able to just drop the extends lines, and change [env:uno] to [env].

Hello community.
I have a question, just trying to understand better.

[env:lolin_d32]
; under here will go all the lolin_d32 specific declarations. 
platform = espressif32
board = lolin_d32                           ; https://www.amazon.de/AZDelivery-Lolin-ESP32-Parent/dp/B086V4NYJX
framework = arduino
board_build.f_cpu = 240000000L              ; sets CPU's frequency to 240 MHz
board_build.f_flash = 80000000L             ; sets flash's RW frequency to 80MHz
upload_speed = 460800                       ; More than that, doesn't not working
monitor_speed = 115200     

Now, I want to have to envs one for macOS and another of linux, for separating port declarations, specifically. How to ago about it?

[lolin_d32:mac]
upload_port = /dev/tty.usbserial-x
monitor_port = /dev/tty.usbserial-x

[lolin_d32:linux]
upload_port = /dev/ttyUSBx
monitor_port = /dev/ttyUSBx

Is this the correct approach?
How does pio knows that it has to look into a random block to search for port declaration?

Why, does automatic port detection not work for you?

It works, but what if I wanted to specify, in an order, as per OS.
Do I have to take the “custom script” approach?

What you can do is

[env] ; global config inherited by all environments
; under here will go all the lolin_d32 specific declarations. 
platform = espressif32
board = lolin_d32                           ; https://www.amazon.de/AZDelivery-Lolin-ESP32-Parent/dp/B086V4NYJX
framework = arduino
board_build.f_cpu = 240000000L              ; sets CPU's frequency to 240 MHz
board_build.f_flash = 80000000L             ; sets flash's RW frequency to 80MHz
upload_speed = 460800                       ; More than that, doesn't not working
monitor_speed = 115200

[env:lolin_d32_mac]
upload_port = /dev/tty.usbserial-x
monitor_port = /dev/tty.usbserial-x

[env:lolin_d32_linux]
upload_port = /dev/ttyUSBx
monitor_port = /dev/ttyUSBx

the user would then have to be responsible for selecting the correct environment in the project environment selector. It will show up as 2 separate environments in PlatformIO.

You might also be able to use Advanced Scripting for setting env["UPLOAD_PORT"], this will override the autodetect logic when done correctly.

1 Like