You wrote:
I'm a very beginner with electronics [...] the looping system feels
pretty awkward
I think these two statements are highly correlated. It feels awkward to
you simply because you are not used to it.
So what I understood is Arduino loop always executes based on any
values from sensors while in the loop.
This sounds like a misunderstanding. The Arduino loop() is a function
you write, and whether its behavior is “based on any values from
sensors” or not is up to you. The main() function provided by the
Arduino core library will just call your loop() repeatedly.
I tried to stop the loop using exit(0);
As explained by Tom L. in his answer, there is nowhere to exit to. In
this kind of embedded system, exit() essentially means “stop doing any
useful work”. On AVR microcontrollers (like in the Nano), exit() is
implemented as an empty infinite loop running with interrupts disabled.
I believe [sleeping] will reduce the load on Arduino and of course
since no looping it will not get heated at all.
Heat? What heat? The CPU core of the Arduino does not generate heat. Not
at any significant level. Think about this: it's clocked at 16 MHz.
Yes, those are megahertz: snail pace! The MCU can get hot if you
have it source or sink too much current, but this is completely
unrelated to CPU load.
I am trying to build an external simple interrupt hardware system
[...] which interrupts Arduino in a specified interval, say 20 sec.
Since you come from the software world, you probably know about
“premature optimization”: this is exactly what you are doing here. I
recommend you stop right now. Do not build into your system complexity
that may not be useful. Instead, start simple: read the Blink without
delay[] Arduino tutorial, and apply this technique to solve your
problem. In a nutshell, you will put, inside your loop(), something
like:
if (millis() - previousMillis >= JOB_PERIOD) {
do_the_job();
previousMillis += JOB_PERIOD;
}
Note that the tutorial I mentioned would instead do something like
previousMillis = millis();, which is fine if you want to ensure that
JOB_PERIOD is the minimum time between the jobs. The code above,
instead, assumes you want to enforce an average period.
Once you have this working, test it, and see whether you do need to
optimize it. There are two aspects that could be optimized: current
consumption and period accuracy. Either may be useful for your
particular application. Or none. Or both. It all depends on your
specific requirements.
Current consumption
There is a low hanging fruit here. You can put the CPU to sleep on every
loop iteration, simply by calling sleep_mode():
#include <avr/sleep.h>
const uint32_t JOB_PERIOD = 20000; // 20 seconds
void do_the_job()
{
// The stuff you have to do every 20 seconds.
}
void loop()
{
static uint32_t previousMillis;
if (millis() - previousMillis >= JOB_PERIOD) {
do_the_job();
previousMillis += JOB_PERIOD;
}
sleep_mode();
}
The Arduino core library has a timer interrupt triggered every
1024 µs. This is the interrupt responsible of updating the variable
that millis() returns, and it will wake you up. With the code above,
the Arduino will be awake for only a few CPU cycles per iteration
(update millis(), subtract, compare) and spend most of its time
sleeping. In the default sleep mode, only the CPU does sleep. But it is
also the only mode in which the timer does not sleep, and is thus the
appropriate mode here.
The trick above should suppress most of the power consumption of the
CPU. If it's still consuming too much for your liking (i.e. if you want
your Nano to run for years on a couple of AA cells), you should know
there are ways to push the microcontroller into the ultra-low power
realm. But it is not so simple, and you will have to tune not only the
software, but also the hardware. Your journey into microamp hunting
should start by reading Power saving techniques for
microprocessors, by Nick Gammon. The link has already been
mentioned in Chirag Patel's answer.
Period accuracy
The Arduino Nano being clocked from a ceramic resonator, you should
expect its timing accuracy to be pretty poor. The standard solution for
when you need accurate timings is to use an RTC. You could query the RTC
periodically to ask for the current time or, better yet, you can choose
an RTC with “alarm” capability. This is not unlike an alarm clock: you
program it to send you an interrupt signal at a time of your choosing.
Read the manual of your RTC for details.