Code Portability Between IDEs
Code Portability Between IDEs
Overview
Section titled “Overview”This section covers how to transfer ESP32 code between PlatformIO and Arduino IDE. By the end of this section, you will be able to:
- Understand the structural differences between PlatformIO and Arduino IDE projects
- Convert a PlatformIO multi-file project to Arduino IDE format
- Identify and fix common portability issues (function prototypes, file extensions)
- Maintain a single codebase that works in both environments
Prerequisites
Section titled “Prerequisites”- PlatformIO project structure (01-05)
- Arduino IDE setup (01-04)
Key Concepts
Section titled “Key Concepts”Why Portability Matters
Section titled “Why Portability Matters”This course’s code examples are developed in PlatformIO (VS Code), but some users prefer the Arduino IDE. The two environments have structural differences:
| Aspect | PlatformIO | Arduino IDE |
|---|---|---|
| Main File | src/main.cpp | sketch_folder/sketch_name.ino |
| Additional Files | src/*.cpp, src/*.h, include/*.h | .ino files in the same folder |
| Library Management | platformio.ini (declarative) | Library Manager (GUI) |
| Function Prototypes | Required | Auto-generated (not required) |
| File Extensions | .cpp, .h | .ino |
| Configuration | platformio.ini | Tools → Board menu |
PlatformIO File Structure
Section titled “PlatformIO File Structure”platformio_project/ ├── platformio.ini # Configuration ├── src/ │ ├── main.cpp # Main code │ ├── wifi_mqtt.h # Wi-Fi/MQTT code (header with implementation) │ └── credentials.h # SSID, password ├── include/ # Additional headers ├── lib/ # Private libraries └── .pio/ # Build artifactsArduino IDE File Structure
Section titled “Arduino IDE File Structure”arduino_sketch/ ├── sketch.ino # Main file (same name as the folder) ├── wifi_mqtt.ino # Additional code tab ├── credentials.ino # Credentials tab └── (no configuration file — settings in IDE menu)Implementation Steps
Section titled “Implementation Steps”Step 1: Export PlatformIO Source Files
Section titled “Step 1: Export PlatformIO Source Files”- Locate your PlatformIO project folder
- Copy the contents of the
src/directory:main.cppwifi_mqtt.hcredentials.h
Step 2: Create the Arduino IDE Folder Structure
Section titled “Step 2: Create the Arduino IDE Folder Structure”- Create a new folder (e.g.,
ESP32_Basic_Sketch) - Create an
.inofile with the same name as the folder:ESP32_Basic_Sketch.ino - Copy the content from
main.cppinto this.inofile
Step 3: Convert Main File (main.cpp → .ino)
Section titled “Step 3: Convert Main File (main.cpp → .ino)”Before (PlatformIO main.cpp):
#include <Arduino.h>#include <WiFi.h>#include "credentials.h"#include "wifi_mqtt.h"
void setup() { Serial.begin(115200); // ...}
void loop() { // ...}After (Arduino IDE .ino):
#include <WiFi.h>
// PlatformIO includes become standard includes// The .h files need to be converted to .ino tabs
void setup() { Serial.begin(115200); // ...}
void loop() { // ...}Key changes:
- Remove
#include <Arduino.h>(Arduino IDE adds this automatically) - Remove
#include "credentials.h"— these will become separate.inotabs - Remove
#include "wifi_mqtt.h"— this will also become a separate.inotab
Step 4: Convert Header Files to .ino Tabs
Section titled “Step 4: Convert Header Files to .ino Tabs”wifi_mqtt.h → Create a new tab in Arduino IDE (Ctrl+Shift+N or the dropdown arrow) named wifi_mqtt.ino:
// wifi_mqtt.ino — Paste the content from wifi_mqtt.h
#include <WiFi.h>#include <PubSubClient.h>
WiFiClient wifiClient;PubSubClient mqttClient(wifiClient);
void connectToWiFi() { Serial.print("Connecting to Wi-Fi"); WiFi.begin(ssid, password); // ...}
void mqttCallback(char* topic, byte* payload, unsigned int length) { // ... same content as wifi_mqtt.h}
void connectToMQTT() { mqttClient.setServer(mqttServer, mqttPort); mqttClient.setCallback(mqttCallback); // ...}credentials.h → Create another tab named credentials.ino:
const char* ssid = "YourWiFiSSID";const char* password = "YourWiFiPassword";const char* mqttServer = "192.168.1.100";const int mqttPort = 1883;Step 5: Handle Function Prototypes (PlatformIO vs Arduino IDE)
Section titled “Step 5: Handle Function Prototypes (PlatformIO vs Arduino IDE)”PlatformIO requires explicit function prototypes:
// PlatformIO: prototypes requiredvoid connectToWiFi();void connectToMQTT();void mqttCallback(char* topic, byte* payload, unsigned int length);void sendSensorData();
void setup() { // ... connectToWiFi(); // OK — prototype declared above}
void connectToWiFi() { // implementation}Arduino IDE auto-generates prototypes for .ino files, so explicit prototyping is optional:
// Arduino IDE: prototypes auto-generated// You can still add them, but they are not required
void setup() { connectToWiFi(); // OK — Arduino IDE creates prototype automatically}
void connectToWiFi() { // implementation}For cross-platform compatibility, add prototypes with a conditional:
#ifdef PLATFORMIO // Explicit prototypes for PlatformIO's strict compiler void connectToWiFi(); void connectToMQTT(); void mqttCallback(char* topic, byte* payload, unsigned int length);#endifAlternatively, place function definitions before setup() in the main file:
// This works in both environments — define before setup()void connectToWiFi() { // implementation}
void setup() { connectToWiFi(); // Works — function already defined}Step 6: Update platformio.ini Dependencies — Manual Arduino IDE Installation
Section titled “Step 6: Update platformio.ini Dependencies — Manual Arduino IDE Installation”PlatformIO auto-downloads libraries declared in lib_deps. In Arduino IDE, you must install them manually via Library Manager.
platformio.ini (source):
lib_deps = knolleary/PubSubClient @ ^2.8 bblanchon/ArduinoJson @ ^7.0 adafruit/DHT sensor library @ ^1.4Arduino IDE installation:
- Tools → Manage Libraries (Ctrl+Shift+I)
- Search each library name and click Install
- Ensure versions match the PlatformIO specification
Step 7: Platform-Specific Code Sections
Section titled “Step 7: Platform-Specific Code Sections”For code that must behave differently in each environment:
// Platform detection#if defined(PLATFORMIO) const char* projectVersion = "2.0.0 (PlatformIO)";#elif defined(ARDUINO_ARCH_ESP32) const char* projectVersion = "2.0.0 (Arduino IDE)";#endif
void setup() { Serial.begin(115200); Serial.println(projectVersion);
#if defined(PLATFORMIO) // PlatformIO-specific: maybe different pin mapping const int ledPin = 2; #else // Arduino IDE-specific fallback const int ledPin = 13; // Some boards have LED on pin 13 #endif
pinMode(ledPin, OUTPUT);}Step 8: Complete Arduino IDE Conversion Checklist
Section titled “Step 8: Complete Arduino IDE Conversion Checklist”-
#include <Arduino.h>removed (causes compile error in Arduino IDE) - All
.hfiles converted to.inotabs (same folder as main.ino) -
#include "filename.h"changed to match.inotab names - Required libraries installed via Library Manager
- Board selected correctly (Tools → Board → ESP32 Arduino)
- Port selected correctly
- Upload speed set (Tools → Upload Speed → 921600)
- Sketch compiles without errors
Verification
Section titled “Verification”- The same code compiles and runs in both PlatformIO and Arduino IDE
- Arduino IDE does not report “missing function prototype” errors
- Library versions match between both environments
- Serial output is identical from both builds
- MQTT and Wi-Fi behavior is identical
Troubleshooting
Section titled “Troubleshooting””Arduino.h: No such file or directory”
Section titled “”Arduino.h: No such file or directory””Cause: #include <Arduino.h> is used in the .ino file.
Solution: Remove #include <Arduino.h> from the main .ino file. The Arduino IDE prepends it automatically.
“‘credentials_h’ was not declared in this scope”
Section titled ““‘credentials_h’ was not declared in this scope””Cause: The #include "credentials.h" directive expects a .h file, but the Arduino IDE tab is named credentials.ino.
Solutions:
- Rename the tab to
credentials.h(Arduino IDE supports.htabs) - Or remove the
#include— Arduino IDE automatically includes all.inotabs in the sketch folder - Or use
#include "credentials.ino"(not conventional but works)
“Function not declared in this scope” in PlatformIO but works in Arduino IDE
Section titled ““Function not declared in this scope” in PlatformIO but works in Arduino IDE”Cause: PlatformIO requires function prototypes before first use.
Solution: Add prototypes at the top of main.cpp:
// Add these before setup()void connectToWiFi();void connectToMQTT();void mqttCallback(char* topic, byte* payload, unsigned int length);Or rearrange functions so the callee appears before the caller.
Best Practices
Section titled “Best Practices”- Develop in PlatformIO, test in Arduino IDE: PlatformIO is faster and has better tooling, but verify portability
- Use conditional compilation sparingly: It’s better to write compatible code than to use
#ifdefeverywhere - Keep the file structure identical: If your PlatformIO project has
credentials.h, create acredentials.htab in Arduino IDE (not.ino) - Document library versions: Note the library versions used in PlatformIO so they can be matched in Arduino IDE
- Test early, test often: After major code changes, verify the sketch compiles in both environments
- Use
.hextensions in Arduino IDE tabs: Arduino IDE supports.hfiles as tabs, making the transition more natural
Summary
Section titled “Summary”- PlatformIO uses
src/main.cpp+*.hfiles; Arduino IDE uses.inofiles in a single folder - Main conversion steps: rename
main.cppto.ino, convert*.hto.inoor.htabs - Remove
#include <Arduino.h>and#include "filename.h"for Arduino IDE - Add function prototypes for PlatformIO’s stricter compiler
- Install libraries manually in Arduino IDE that PlatformIO auto-downloads
- PlatformIO offers faster compilation and better code organization; Arduino IDE offers simplicity and broad compatibility