stats

ESPnow Mesh

ESPnow is een energie zuinige en snelle manier om korte berichten in de WiFi band uit te wisselen tussen ESP's. Door een broadcast MAC adres te gebruiken kunnen meerdere ESP's tegelijk worden bereikt, echter, alle unit's moeten zich dan wel binnen het bereik van de centrale unit bevinden. Door elke unit het bericht te laten herhalen kunnen we de berichten verder verspreiden. Met een slimme timing en toepassing van light sleep kunnen indrukwekkende afstanden worden overbrugt en een aanzienlijke energie besparing.

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. Na Nmax vindt een tweede, aftellende, herhaling plaats waardoor verzamelde informatie ook weer terug komt bij de basis unit.

Voorbeeld: Wanneer unit 1 het bericht direct van unit 0 ontvangt zal deze dit direct herhalen (tijdslot 1). Wanneer unit 3 en 5 het bericht van unit 0 ontvangen wachten deze 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 herhalen. Maar wanneer unit 4 het bericht (enkel) via unit 7 verneemt kan deze het niet herhalen omdat tijdslot 4 al verstreken is. In dat geval verzend deze unit op Nmax+1 alsnog zijn bericht en komt ook zijn info weer terug bij unit 0. De kans dat dit meerdere buur-units tegelijk betreft is zeer klein.

Bij 14 units en een sync herhaling van 1 Sec rest een theoretische slaap tijd van 970mS. Trekken we daar de nodige software tijd vanaf dan komen we toch nog op een energie besparing van ruim 80% 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 ====
void OnDataRecv(byte *mac, byte *data, byte len) {
  if (data[0] == SYNC) {
     memcpy(&Sync, data, sizeof(Sync));
     cast = Sync.Afz;
     comp = (cast) ? 4 : 10;
     styd = millis() + (Sync.Sync - comp);
     if (cast < Conf.Unit) oke = true;       
     rcvd = true;
  }
}

// ==== MAIN-LOOP ====
void loop() 

  if (low && millis() >= styd) {
    wake = millis();
    low = false;
    wifi_set_opmode(WIFI_STA);
    delay(1);
  }

// ==== Synchro routine ====
  if (rcvd && millis() >= ctyd) {
    ctyd = millis() + 4;
    if (sdir) cast--; else cast++;
    if (cast == Conf.Unit) SendMessage(SYNC);
    if (cast > Conf.Nmax) {
      if (!oke) SendMessage(SYNC);
      sdir = true;
  }

  ...... plaats hier de uit te voeren actie  (bussy)

// ==== modem sleep ====
  if (rcvd && !cast) {
    low = true;
    oke = sdir = rcvd = 0;
    WiFi.mode(WIFI_OFF); 
    delay(1);
  }
  if (low && !bussy)  Sleep(styd - millis());
}

// ==== cpu sleep ====
void Sleep(int sleep) {
  if (sleep > 999) sleep = 997;
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  wifi_fpm_open();
  wifi_fpm_do_sleep(sleep * 1000);
  delay(sleepTime);
}

// ==== TX info ====
void SendMessage(byte type) {
  if (type == SYNC) {
    Sync.Afz = cast;
    Sync.Sync = stijd - millis();
    esp_now_send(CAST, (byte*) &Sync, sizeof(Sync));
  }
}

Bij ontvangst wordt de TX tijd en de sync marge verrekend (styd=millis()+(Sync-10)). Per 'herhaling' wordt het Sync moment geactualiseerd (Sync=styd-millis()) tbv de gebruikte CPU tijd.

Noot:

Heb je vragen of opmerkingen? Stuur me een berichtje en je krijgt alle gewenste informatie!

HOME