Unable to Upload Code via WiFi to Arduino Uno R4 WiFi using PlatformIO in VS Code with Arduino OTA

Hi everyone,

I’m having trouble uploading code to my Arduino Uno R4 WiFi using PlatformIO in Visual Studio Code with the Arduino OTA library. Here’s what I’ve observed.

I can reliably upload code to my Arduino Uno R4 WiFi over WiFi using the IP address with the Arduino IDE. This suggests that the network and device configuration are set up correctly.

When I use PlatformIO in VS Code, I can upload code successfully over a USB connection to the Arduino Uno R4 WiFi.

When I attempt to upload code over WiFi using PlatformIO by specifying the IP address (192.168.1.67) and the Arduino OTA library, the upload process initiates but then fails at the end with the error message: “No device at 192.168.1.67,” which is the target IP address I set.

I can ping the device ip and its host name in the same platformio terminal.

I don’t believe this is a network issue since the Arduino IDE works perfectly fine for WiFi uploads using the same setup. My goal is to keep everything within VS Code for a more streamlined workflow.

Has anyone encountered a similar issue or could offer some guidance on how to resolve this when using the Arduino OTA library with PlatformIO in VS Code? Any help or suggestions would be greatly appreciated!

Thanks in advance!

And with what platformio.ini is that?

platformir.ini

[env:uno_r4_wifi]
platform = renesas-ra
board = uno_r4_wifi
framework = arduino
lib_deps =
knolleary/PubSubClient@^2.8
adafruit/DHT sensor library@^1.4.6
adafruit/Adafruit Unified Sensor@^1.1.14
jandrassy/ArduinoOTA@^1.1.0

Terminal copy paste with the error

Building .pio\build\uno_r4_wifi\firmware.bin
Configuring upload protocol...
AVAILABLE: cmsis-dap, jlink, sam-ba
CURRENT: upload_protocol = sam-ba
Looking for upload port...
Using manually specified: 10.0.20.244
Uploading .pio\build\uno_r4_wifi\firmware.bin
**No device found on 10.0.20.244**
*** [upload] Error 1

No that’s still invoking the program for flashing something via USB; it can’t do the ArduinoOTA upload procedure.

You see that for the Arduino IDE 2 and the Renesas, you also had to copy a file with special instructions for the Arduino IDE 2 to invoke the arduinoOTA program.

You’re missing that part for PlatformIO completely. You need to at least get a copy of the arduinoOTA program (or a package that contains it), then modify use a upload_protocol = custom with an appropriate upload_command to invoke arduinoOTA, with the same parameters that the Arduino IDE 2 would do (this includes IP, password, username, etc.)

See docs.

There doesn’t seem to be a readily-copyable example for PlatformIO in https://github.com/JAndrassy/ArduinoOTA, so I’ll create on and post it later.

Actually, there is an example at

but it requires you to have curl installed and in your %PATH, so it doesn’t use arduinoOTA.exe

Ok thank you for the help. This is a first programming project for me so things click a little slower.

I need to look at the doc a bit closer because I’m having trouble understanding what I need to do. Specifically this:

According to the example you shared, I made a new file called extra_scripts.py and added the linds into platformio.ini.

Running the PlatformIO: Upload command at the bottom blue bar got me some new log messages:

Processing uno_r4_wifi (platform: renesas-ra; board: uno_r4_wifi; framework: arduino)
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/renesas-ra/uno_r4_wifi.html
PLATFORM: Renesas RA (1.4.0) > Arduino Uno R4 WiFi
HARDWARE: RA4M1 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, jlink)
PACKAGES:
 - framework-arduinorenesas-uno @ 1.1.0        
 - tool-bossac @ 1.10901.0 (1.9.1)
 - tool-jlink @ 1.78811.0 (7.88.11)
 - tool-openocd @ 3.1200.0 (12.0)
 - toolchain-gccarmnoneeabi @ 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 25 compatible libraries
Scanning dependencies...
Dependency Graph
|-- PubSubClient @ 2.8.0
|-- DHT sensor library @ 1.4.6
|-- Adafruit Unified Sensor @ 1.1.14
|-- ArduinoOTA @ 1.1.0
|-- WiFiS3 @ 0.0.0
Building in release mode
Checking size .pio\build\uno_r4_wifi\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [==        ]  22.2% (used 7288 bytes from 32768 bytes)
Flash: [===       ]  27.2% (used 71380 bytes from 262144 bytes)
Configuring upload protocol...
AVAILABLE: cmsis-dap, custom, jlink, sam-ba
CURRENT: upload_protocol = custom
Uploading .pio\build\uno_r4_wifi\firmware.bin
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0curl: (6) Could not resolve host: ip_address
*** [upload] Error 6

Again, in vs code terminal, it can ping the IP correctly.

Did you keep

 upload_flags =
   http://arduino:password@ip_address:65280/sketch

unmodified in the platformio.ini? You need to replace ip_address with the actual IP address here.

arduino is the username and password is the password used above. (“HTTP Basic Authentication”). Double check that these are the same values you use in your sketch. These are the default values…

Note that “Arduino” is not the username here but the advertised MDNS hostname.

I just tested this platformio.ini

[env:uno_r4_wifi]
platform = renesas-ra
board = uno_r4_wifi
framework = arduino
lib_deps =
    jandrassy/ArduinoOTA@^1.1.0
extra_scripts = post:extra_scripts.py
upload_protocol = custom
upload_flags =
  http://arduino:password@192.168.0.105:65280/sketch

with the already linked extra_script.py and a src/main.cpp of

#include <WiFiS3.h>
#include <ArduinoOTA.h>

#define SECRET_SSID "XXXXXXXXX"
#define SECRET_PASS "XXXXXXXXXXXX"

char ssid[] = SECRET_SSID;    // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password
int status = WL_IDLE_STATUS;  // the WiFi radio's status

void printWifiStatus();

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  // while (!Serial) {
  // wait for serial port to connect. Needed for native USB port only
  //}

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true)
      ;
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 10 second for connection:
    delay(10000);
  }

  // start the WiFi OTA library with internal (flash) based storage
  // The IDE will prompt for this password during upload
  ArduinoOTA.begin(WiFi.localIP(), "Arduino", "password", InternalStorage);

  // you're connected now, so print out the status:
  printWifiStatus();
  pinMode(LED_BUILTIN, OUTPUT);
}

static unsigned long last_time = 0;
void loop() {
  if(millis() - last_time >= 5000) { 
    printWifiStatus();  //sign of life
    digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) ^ 1);
    last_time = millis();
  }
  // check for WiFi OTA updates
  ArduinoOTA.poll();

}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

And upload works fine.

Also I just placed the needed curl.exe directly in the project folder, next to the platformio.ini.

Hmm ok that worked more. I feel like I’m close! Thanks again for your help. Maybe I one small step away?

I’m now trying to replicate your example exactly, and in a new PlatformIO project called otatest.

My .ini is the same as yours except for the ip address. I have the extra_scripts.py

Here is what I get on the PlatformIO terminal. The table list keeps populating forever. I let it go for about 5 minutes just to be sure.

Building .pio\build\uno_r4_wifi\firmware.bin
Configuring upload protocol...
AVAILABLE: cmsis-dap, custom, jlink, sam-ba
CURRENT: upload_protocol = custom
Uploading .pio\build\uno_r4_wifi\firmware.bin
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 62040    0     0  100 62040      0  59481  0:00:01  0:00:01 --:--:-- 59482
100 62040    0     0  100 62040      0  30242  0:00:02  0:00:02 --:--:-- 30233
100 62040    0     0  100 62040      0  20276  0:00:03  0:00:03 --:--:-- 20274
100 62040    0     0  100 62040      0  15250  0:00:04  0:00:04 --:--:-- 15246
100 62040    0     0  100 62040      0  12220  0:00:05  0:00:05 --:--:-- 12219
100 62040    0     0  100 62040      0  10195  0:00:06  0:00:06 --:--:--     0
100 62040    0     0  100 62040      0   8746  0:00:07  0:00:07 --:--:--     0
100 62040    0     0  100 62040      0   7657  0:00:08  0:00:08 --:--:--     0
100 62040    0     0  100 62040      0   6810  0:00:09  0:00:09 --:--:--     0

This is a screenshot of the folder structure with curl.exe, which I downloaded here
image

This is the .ini just in case:

[env:uno_r4_wifi]
platform = renesas-ra
board = uno_r4_wifi
framework = arduino
lib_deps =
    jandrassy/ArduinoOTA@^1.1.0
extra_scripts = post:extra_scripts.py
upload_protocol = custom
upload_flags =
  http://arduino:password@10.0.20.244:65280/sketch

One more thing. On my original Arduino script I have this code to signal a start of OTA. I actually get this message in the log, but it doesn’t actually load the script…

  // OTA Setup
    ArduinoOTA.onStart([]() {
        // OTA update starting
        printAll("Starting OTA update...");
    });

Can you try it with my exact src/main.cpp from above but with just filled out SSID and Password strings? Upload it once via USB to get a good start (comment out all the upload_xx and extra_scripts stuff in the platformio.ini)

Yes, trying my best to do exactly that. I set it up again from scratch and followed the steps you just described.

  • The USB load worked great with the commented lines out. I then added them back in.
  • I was able to get your code to work over OTA today. I have no idea what I did differently but I suppose today I did something different than yesterday… (log shared below)
  • I then tried to load my code over OTA the same way with the same .ini and it failed (log shared below). So maybe somethings complex about my code? As a note, my OTA lines of code are identical so IDK.
  • Now I tried to “reset” this lab test back to try mimicking your files. So I reloaded your code via USB to get it ready. And over the OTA update after that I get:
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 62040    0     0  100 62040      0   769k --:--:-- --:--:-- --:--:--  766k
curl: (56) Recv failure: Connection was reset
*** [upload] Error 56

.
.

This is the log from the first time I was able to load your code over OTA **and** I was able to then load my code in there via OTA.
Building .pio\build\uno_r4_wifi\firmware.bin
Configuring upload protocol...
AVAILABLE: cmsis-dap, custom, jlink, sam-ba
CURRENT: upload_protocol = custom
Uploading .pio\build\uno_r4_wifi\firmware.bin
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 62040    0     0  100 62040      0  56710  0:00:01  0:00:01 --:--:-- 56761
100 62040    0     0  100 62040      0  29509  0:00:02  0:00:02 --:--:-- 29514
100 62040    0     0  100 62040      0  19944  0:00:03  0:00:03 --:--:-- 19948
100 62040    0     0  100 62040      0  15061  0:00:04  0:00:04 --:--:-- 15061
100 62040    0     0  100 62040      0  12099  0:00:05  0:00:05 --:--:-- 12100
100 62040    0     0  100 62040      0  10111  0:00:06  0:00:06 --:--:--     0
100 62040    0     0  100 62040      0   8683  0:00:07  0:00:07 --:--:--     0
100 62042    0     2  100 62040      0   8533  0:00:07  0:00:07 --:--:--     0
100 62042    0     2  100 62040      0   8533  0:00:07  0:00:07 --:--:--     0
[SUCCESS] Took 13.55 seconds

.
.

My attempt to load code on the my own code instead of the main.cpp:
CONFIGURATION: https://docs.platformio.org/page/boards/renesas-ra/uno_r4_wifi.html
PLATFORM: Renesas RA (1.4.0) > Arduino Uno R4 WiFi
HARDWARE: RA4M1 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, jlink)
PACKAGES:
 - framework-arduinorenesas-uno @ 1.1.0
 - tool-bossac @ 1.10901.0 (1.9.1)
 - tool-jlink @ 1.78811.0 (7.88.11)
 - tool-openocd @ 3.1200.0 (12.0)
 - toolchain-gccarmnoneeabi @ 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 25 compatible libraries
Scanning dependencies...
Dependency Graph
|-- ArduinoOTA @ 1.1.0
|-- PubSubClient @ 2.8.0
|-- DHT sensor library @ 1.4.6
|-- Adafruit Unified Sensor @ 1.1.14
|-- WiFiS3 @ 0.0.0
Building in release mode
Compiling .pio\build\uno_r4_wifi\src\PoolController-Arduino.cpp.o
Linking .pio\build\uno_r4_wifi\firmware.elf
Building D:\OneDrive\Documents\VS Code\PoolController\.pio\build\uno_r4_wifi/firmware.bin
Checking size .pio\build\uno_r4_wifi\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [==        ]  22.2% (used 7288 bytes from 32768 bytes)
Flash: [===       ]  27.3% (used 71508 bytes from 262144 bytes)
Building .pio\build\uno_r4_wifi\firmware.bin
Configuring upload protocol...
AVAILABLE: cmsis-dap, custom, jlink, sam-ba
CURRENT: upload_protocol = custom
Uploading .pio\build\uno_r4_wifi\firmware.bin
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 71508    0     0  100 71508      0  64868  0:00:01  0:00:01 --:--:-- 64889
100 71508    0     0  100 71508      0  33878  0:00:02  0:00:02 --:--:-- 33890
100 71508    0     0  100 71508      0  22925  0:00:03  0:00:03 --:--:-- 22926
100 71508    0     0  100 71508      0  17324  0:00:04  0:00:04 --:--:-- 17326
100 71508    0     0  100 71508      0  13923  0:00:05  0:00:05 --:--:-- 13925
100 71508    0     0  100 71508      0  11638  0:00:06  0:00:06 --:--:--     0
100 71508    0     0  100 71508      0   9997  0:00:07  0:00:07 --:--:--     0
100 71508    0     0  100 71508      0   8762  0:00:08  0:00:08 --:--:--     0

Adding in wireshark just in case on the latest fail when trying to only load your code. I can’t figure out why I struggle getting the same result every time?

The behavior might differ with curl.exe and arduinoOTA.exe as uploader. Maybe curl sends the data too quickly for the ESP32 to handler.

I’ve also made sure that my sketch has a non-blocking loop(). So, no delay() used such that ArduinoOTA.poll() is called as quickly as possible.

Also, the OTA only works with the firmware size is at most half of the flash size (of 256kB), since the Uno R4 stores the incoming firmware in the upper half of the flash.