Elegant würde ich das über eine Klasse machen.
Nennen wir sie z.B. TimedCounter, deren Instanzen mit einer Periodendauer erzeugt werden, deren aktuellen Zähler man abfragen kann, und fragen kann, ob seit dem letzten abfragen was zu tun ist.
( Soweit deine Aufgabenstellung )
class TimedCounter
{
unsigned long _z;
unsigned long _lastrun;
public:
TimedCounter(unsigned long zyklus); // Konstruktor
unsigned long getCounts(); // liefert den Zähler
boolean trigger(); // sollte zyklisch aufgerufen werden: true wenn seit dem letzten Mal der Zähler erhöht wurde
};
TimedCounter t1(1000); // zählt im Sekunden-Takt
TimedCounter t2(5000); // zählt im 5 Sekunden-Takt
TimedCounter tarray[] = {
TimedCounter(500),
TimedCounter(3000)
};
void loop()
{
if ( t1.trigger() ) doSekundentask();
}
void doSekundentask()
{
// wird jede Sekunde einmal gestartet
}
Das kann man erweitern um eine callback Funktion je Zähler, die jeweils im gewünschten Zyklus aufgerufen wird,
und um eine generelle Funktion für alle, die einmal in loop aufgerufen wird und alle Zähler bearbeitet, wenn es wirklich viele werden...
Bei deinen Anforderungen würde ich keine Hardwaretimer - Interrupts verwenden, damit die callback Funktionen auch mal ein bisschen länger dauern können und alles machen dürfen.
Detailfragen wie z.B. "wenn ein Zyklus verpasst wurde, soll er ausfallen oder gleich hintereinander mehrfach triggern" kann man so oder so lösen, muss man nur bedenken ...
Wie immer, sowas ähnliches gibts sicher schon fertig.
(Suchen und verstehen/lernen ob es genau das ist was man braucht und anpassen, ist auch Aufwand)
Ob man die callback Funktionen hochtrabend "Prozesse" nennen sollte, ist Geschmackssache 