Arduino in VsCode - without the redundant C bs?

The lack of github Copilot is a sad thing when using the otherwise nice ArduinoIDE
I know about PlatformIO.
But then, using it, I teleport back to the 80's with all of the meaningless, redundant C declarations and header files.

Is there something that modernizes C++ , for VsCode, like Arduino does?

The "modernization" is a crutch. If you want to be a C++ programmer, learn the language.

2 Likes

What?
PlatformIO :hearts:

If they are redundant, don't use them :smiley: I'm sure that you know that you soon will find out that they are not that redundant.

Ah, so you all dislike that Arduino does not force you to declare things twice and use .h files ?
C loyalty before convenience ?

Your Arduino projects must be extremely trivial without any .h files. For example:

#include <TimeLib.h>
#include <LittleFS.h>
#include <SD.h>
#include <FastLED.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
#include <Servo.h>
#include <Wire.h>
#include <SPI.h>
#include <WiFi.h>

my most complex yet is across eight .ino files, and only three .h files, and I had a hard time making it compile outside Arduino, because I never declared functions again in .h files, just used them for defines, consts, and some vars.

Yes, that's the simplicity i love, C++ feels extremely old-fashion after I started to use Arduino years ago.
I do not look for purism and strict ANSI C ideas, just simplicity. The easy way of Arduino is super-useful, most projects do not require minimal latency and direct register-configurations. - hence I use Arduino where suitable. And this simplicity is beautiful - that's why I thought people had a solution to automate much of the C-ideas from the time of 640kB RAM of declaring the same things in more than one place.

It seems that sticking with the Arduino IDE is the right choice for you, given your apparent abilities and skill level.

2 Likes

@gfvalvo - maybe you are right, I loath too much doing things twice for old times sake, to do it properly, when I know about a simpler way. :slight_smile:

This is slightly long to try to explain what can go wrong with the 'simplicity'. As long as it all works, be happy; but when the 'simplicity' results in compiler errors, you will cry if you don't know what to look for.

Unfortunately that simplicity might come at a cost. Before the IDE passes the sketch to the compiler it runs an application known as the builder. This application does a few things:

  1. It adds the line #include <Arduino.h> at the beginning of the main sketch.
  2. It merges all ino files into one big file.
  3. It generates so-called function prototypes of the functions in the ino file(s). The builder is not perfect and can do the wrong thing here.
  4. Possibly other stuff; I think it's also responsible for detecting the "libraries used" and that way the IDE knows which library files need to be compiled.

Assume that you have a sketch with two ino files.
Main file (1244744.0.1.ino)

const uint8_t ledPin = LED_BUILTIN;

void setup()
{
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  blink();
}

void blink()
{
  setPin(ledPin, HIGH);
  delay(1000);
  setPin(ledPin, LOW);
  delay(1000);
}

second ino file (fileA.ino)

void setPin(uint8_t pin, uint8_t status)
{
  digitalWrite(pin, status);
  Serial.print(F("pin "));
  Serial.print(pin);
  Serial.print(F(" set to "));
  Serial.println(status);
}

The combination of these two is nothing more than the blink example but with a dedicated function to set a pin LOW or HIGH (setPin() in fileA.ino) and a dedicated function for blink (blink() in 1244744.0.1.ino).

Steps 1 .. 3 given above will result in the below file actually being passed to the compiler

#include <Arduino.h>
#line 1 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
const uint8_t ledPin = LED_BUILTIN;

#line 3 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void setup();
#line 9 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void loop();
#line 14 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void blink();
#line 1 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/fileA.ino"
void setPin(uint8_t pin, uint8_t status);
#line 3 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void setup()
{
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  blink();
}

void blink()
{
  setPin(ledPin, HIGH);
  delay(1000);
  setPin(ledPin, LOW);
  delay(1000);
}

#line 1 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/fileA.ino"
void setPin(uint8_t pin, uint8_t status)
{
  digitalWrite(pin, status);
  Serial.print(F("pin "));
  Serial.print(pin);
  Serial.print(F(" set to "));
  Serial.println(status);
}

All lines starting with #line indicate where the builder took information from. Of particular interest are the lines 5-12 which are the so-called function prototypes.

#line 3 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void setup();
#line 9 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void loop();
#line 14 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino"
void blink();
#line 1 "/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/fileA.ino"
void setPin(uint8_t pin, uint8_t status);

The compiler needs to know e.g. what a function looks like when you can use it so it can check e.g. the type of the parameters that you pass a give a warning or error if you do it wrong.

As said, the builder is not perfect. It might place the function prototype in the wrong place and as a result the your sketch will not compile.

And that is why more experienced users prefer to use .h (and .cpp) files so they can tell the compiler what the functions look like and decide where that prototype will be placed.

Now you're editing (in this example) the main ino file and you accidentally removed the last } of the blink function.
The error that you get is

/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino: In function 'void blink()':
1244744.0.1:16:3: error: 'setPin' was not declared in this scope
   setPin(ledPin, HIGH);
   ^~~~~~
/home/wim/Downloads/arduino-1.8.19/portable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/1244744.0.1.ino:16:3: note: suggested alternative: 'ledPin'
   setPin(ledPin, HIGH);
   ^~~~~~
   ledPin
fileA:2:1: error: a function-definition is not allowed here before '{' token
 {
 ^
fileA:8:1: error: expected '}' at end of input
 }
 ^
exit status 1
'setPin' was not declared in this scope

The errors basically refer to an error in fileA.ino, not to an error in the main ino file. If you don't know, you will be pulling your hair out to find the mistake because the error message basically puts you on the wrong foot. You can find the problem when inspecting the file that is actually compiled.

  1. The function prototype for setPin() is missing.
  2. The end of the code looks like
void blink()
{
  setPin(ledPin, HIGH);
  delay(1000);
  setPin(ledPin, LOW);
  delay(1000);

#line 1 "/home/wim/Downloads/arduino-1.8.19/sportable/sketchbook/forum.arduino.cc/1244744/1244744.0.1/fileA.ino"
void setPin(uint8_t pin, uint8_t status)
{
  digitalWrite(pin, status);
  Serial.print(F("pin "));
  Serial.print(pin);
  Serial.print(F(" set to "));
  Serial.println(status);
}

and shows the missing } at the end of the blink() function.

If you would have used a .h file for the function prototype and a ,cpp file for the implementation, you would not have had that problem; it will still fail to compile but you will now have a clearer indication where the problem lays.

Note:
If you enable verbose output during compilation under file / preferences, you can find the file that is actually compiled. Search the output for .ino.cpp (e.g. after copying the output in a text editor) and it will give you the path. Note: code tags omitted on purpose.

Using board 'nano' from platform in folder: /home/wim/Downloads/arduino-1.8.19/portable/packages/arduino/hardware/avr/1.8.6
Using core 'arduino' from platform in folder: /home/wim/Downloads/arduino-1.8.19/portable/packages/arduino/hardware/avr/1.8.6
Detecting libraries used...
/home/wim/Downloads/arduino-1.8.19/portable/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/wim/Downloads/arduino-1.8.19/portable/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/home/wim/Downloads/arduino-1.8.19/portable/packages/arduino/hardware/avr/1.8.6/variants/eightanaloginputs /tmp/arduino_build_206826/sketch/1244744.0.1.ino.cpp -o /dev/null

In this case I did find "/tmp/arduino_build_206826/sketch/1244744.0.1.ino.cpp".

1 Like

Yes, this I have experienced several times, and for some projects git was of huge help (letting me compare).
I see that this alone may be a good reason to stick to .h files.
Is your experience that Arduino libraries and all works fine with PlatformIO , or do you find yourself searching for alternatives?

Using a more than one .ino file in the user project is allowed, although considered to be a bad style. Using several .ino files in the library is unacceptable, which is why all good libraries are written using standard .c/.cpp and .h file pairs.
All such libraries are compatible with Platformio

9 posts were split to a new topic: Add GitHub Copilot to Arduino IDE

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.