Trouble with uploading on Leonardo

I try to make simple project and face to a problem with uploading firmware on Leonardo board.

Log:

Project does not have dependencies
Looking for upload port...
Auto-detected: COM26
Forcing reset using 1200bps open/close on port COM26
Waiting for the new upload port...
Uploading .pioenvs\leonardo\firmware.hex
avrdude: ser_open(): can't open device "\\.\COM26": �� ������� ����� ��������� ����.

avrdude done.  Thank you.
 
*** [upload] Error 1
 [ERROR] Took 7.31 seconds

My platformio.ini:

[env:leonardo]
platform = atmelavr
board = leonardo
framework = arduino

Blink.cpp:

#include <Arduino.h>

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
  delay(500);
}

platformio serialports list say:

COM1
----
Hardware ID: ACPI\PNP0501\1
Description: Последовательный порт (COM1)

COM26
-----
Hardware ID: USB VID:PID=2341:8036 LOCATION=1-2.2
Description: Arduino Leonardo (COM26)

When I tried to upload this project on Nano board everything was OK and worked correctly.

Log with ‘-v’ option:

Looking for upload port...
Auto-detected: COM26
Forcing reset using 1200bps open/close on port COM26

Waiting for the new upload port...
Uploading .pioenvs\leonardo\firmware.hex

Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
 
Using Port                    : COM26
Using Programmer              : avr109
Overriding Baud Rate          : 57600

avrdude: Version 6.3, compiled on Sep 12 2016 at 17:24:16
System wide configuration file is "C:\Users\Roman\.platformio\packages\tool-avrdude\avrdude.conf"
avrdude: ser_open(): can't open device "\\.\COM26": �� ������� ����� ��������� ����.
avrdude done.  Thank you.
*** [upload] Error 1
 [ERROR] Took 6.83 seconds

So, I tried upload trough Arduino IDE with the detailed output and got:

Forcing reset using 1200bps open/close on port COM26
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM26, } => {}
PORTS {COM1, COM26, } / {COM1, COM27, } => {COM27, }
Found upload port: COM27
C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avrdude -CC:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -patmega32u4 -cavr109 -PCOM27 -b57600 -D -Uflash:w:C:\Users\Roman\AppData\Local\Temp\build5981244134228677886.tmp/Blink.cpp.hex:i 

avrdude: Version 6.0.1, compiled on Apr  3 2014 at 23:12:16
     Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
     Copyright (c) 2007-2009 Joerg Wunsch

     System wide configuration file is "C:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf"

     Using Port                    : COM27
     Using Programmer              : avr109
     Overriding Baud Rate          : 57600
     AVR Part                      : ATmega32U4
     Chip Erase delay              : 9000 us
     PAGEL                         : PD7
     BS2                           : PA0
     RESET disposition             : dedicated
     RETRY pulse                   : SCK
     serial program mode           : yes
     parallel program mode         : yes
     Timeout                       : 200
     StabDelay                     : 100
     CmdexeDelay                   : 25
     SyncLoops                     : 32
     ByteDelay                     : 0
     PollIndex                     : 3
     PollValue                     : 0x53

It seems that PlatformIO try to connect to COM26 without waiting for new port (com27) will be open and Leonardo will be ready for uploading.

Found the same issue: [Bug report] Cannot upload firmware to Arduino Leonardo. Port enumerated too quickly · Issue #691 · platformio/platformio-core · GitHub

So, I just change sleep() argument from 1 to 3 and then uploading run correctly. But when I return sleep argument from 3 to 1 uploading process staty correctrly yet.

I have no idea what this was. But at least I know where the root of this issue.

Do you mean that it works now without any changes to PlatformIO source code?

It seems I was wrong. My fix work definitely unstable. Even when I run uploading several times as a series. I’m planning to spend some time to solve this problem tonight. May be I’ll get some more information.

After some time I found solution fo my problem. I changed the logic of waiting for new port (instead of sleep(1) ). So, I’ve got a new WaitForNewSerialPort function:

pipiupload.py:

    def WaitForNewSerialPort(env, before):
        print "Waiting for the new upload port..."
        prev_port = env.subst("$UPLOAD_PORT")
        new_port = None
        elapsed = 0

        resetTime = 0
        while resetTime < 5:
            now = util.get_serialports()
            if not any(p['port'] == prev_port for p in now):
                before = now
                break
            sleep(0.05)
            resetTime += 0.05

        while elapsed < 5 and new_port is None:
            now = util.get_serialports()
            for p in now:
                if p not in before:
                    new_port = p['port']
                    break
            before = now
            sleep(0.25)
            elapsed += 0.25

        if not new_port:
            for p in now:
                if prev_port == p['port']:
                    new_port = p['port']
                    break
        print "result: " + repr(new_port)

        if not new_port:
            sys.stderr.write("Error: Couldn't find a board on the selected port. "
                             "Check that you have the correct port selected. "
                             "If it is correct, try pressing the board's reset "
                             "button after initiating the upload.\n")
            env.Exit(1)

        return new_port

Not sure about 100% correct of my code (Python isn’t my favorite lang). But it’s works for me. At least for now.

See