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:
- It adds the line
#include <Arduino.h>
at the beginning of the main sketch.
- It merges all ino files into one big file.
- 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.
- 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.
- The function prototype for
setPin()
is missing.
- 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".