
Een slimme timing wordt bereikt door de esp's een tijdbasis te geven die is afgeleid van de millis() tijd van de basis unit. Een bericht van 32 byte waarin ook het nummer van de verzender is opgenomen, duurt met ESPnow minder dan 2mS. Alle esp's wachten gelijktijdig op dit sync signaal. Na ontvangst wordt het bericht door de unit her-uitgezonden in zijn eigen tijdslot met zichzelf als afzender. Op deze wijze wordt een bericht verspreidt zonder dat de berichten elkaar verstoren.
Wanneer unit 3 en 5 het bericht direct van unit 0 ontvangen wachten deze resp. 6 en 10 mS alvorens het bericht in tijdslot 3 en 5 te herhalen. Krijgt unit 7 het bericht via unit 5 dan zal deze het bericht in tijdslot 7 (t.o.v unit 0) herhalen. Maar wanneer unit 4 het bericht (enkel) via unit 7 verneemt kan deze het niet herhalen omdat tijdslot 4 al verstreken is. Om dit te ondervangen verloopt de tijdslot volgorde afwisselend op en aftellend en golven daarmee de berichten ook weer terug naar de bron.
Bij 14 units en een sync herhaling van 1 Sec rest een theoretische sleep tijd van 9970mS. Trekken we daar de nodige software tijd vanaf dan komen we toch nog op een energie besparing van ruim 90% voor de inactieve periodes van de esp's. De onderdelen hieronder betreft een mesh netwerk voor een regie met veertien ESP-01's in het veld.
// ==== RX callback routine ====
void OnDataRecv(byte *mac, byte *data, byte len) {
if (data[0] == SYNC) {
memcpy(&Sync, data, sizeof(Sync));
corr = Sync.Mils + 2 - millis();
styd = Sync.Sync - corr - 10;
cast = Sync.Afz & 127;
sdir = (Sync.Afz & 128);
rcvd = true;
}
}
// ==== Synchro routine ====
if (rcvd && millis() > ctyd) {
ctyd = millis() + 2;
if (cast == Conf.Unit) SendMessage(SYNC);
if (sdir) cast--; else cast++;
if (cast > Conf.Umax) cast = 0;
if (!cast) rcvd = fals;
}
wait = (millis() > styd);
if (!Bussy && !rcvd && !wait) {
Sleep(styd - millis());
}
// ==== TX info routine ====
void SendMessage(byte type) {
Sync.Afz = Conf.Unit + (sdir) ? 128 : 0;
Sync.Mils = millis() + corr;
esp_now_send(CAST, (byte*) &Sync, sizeof(Sync));
}
// ==== light sleep function ====
void Sleep(unsigned long sleep) {
if (sleep > 999) sleep = 999;
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(sleep * 1000);
delay(sleep);
WiFi.mode(WIFI_STA);
}
De sleep routine wordt enkel doorlopen wanneer de unit idle is en gewacht wordt tot het sync moment aanbreekt. Zodra de nieuwe sync info binnen komt wordt de syncro routine doorlopen. Wanneer de unit weer idle is zal de sleep routine weer worden doorlopen.
Noot:
Heb je vragen of opmerkingen? Stuur me een berichtje en je krijgt alle gewenste informatie!