когда то давным давно тоже делал библиотеку для псевдопотоков.
controll.run(); должен быть в loop.
вы же понимаете что никакой многопоточности в ардуино быть не может. controll.run в каждой итерации loop проверяет все подключенные обработчики/thread и если пришло их время запускает эти функции. никакого волшебства, ровно как и никаких реальных потоков.
если вы не вызываете controll.run в loop то эти обработчики никогда не будут запущены.
также учтите что код в обработчиках не выполняется параллельно!!!
то есть если 2 функции(thread) которые там добавлены выполняются каждая по 1 секунде (например они содержат sleep внутри себя) то они будут выполнены ровно по очереди и вместе будут выполняться 2 секунды, а не 1 секунду как было бы при честной многопоточности.
либо еще вариант делать их запуск по условию
initTime = millis() + 5000;
loop() {
if (millis() < initTime) {
controll.run();
}
}
controll.run будет запускаться только первые 5 сек. если вы не хотите получить лишние накладные расходы при обычной работе после запуска.
UPD: читайте как работают EventLoop в любых языках программирования и библиотеках.