Macademia'nın robotik ve mühendislik programı · ücretsiz seviye tespiti ve kişisel öğrenme yolu

2. ünite / 10

Wi-Fi: bağlanmak, kopmak, yeniden bağlanmak

İstemci (STA) ve erişim noktası (AP) kipleri, WiFi.status() durumları, olaylar, RSSI ve üstel geri çekilmeyle bloklamayan yeniden bağlanma.

Bu ünitenin sonunda

  • STA, AP ve AP+STA kiplerini ve kullanım yerlerini ayırt etmek
  • WiFi.status() durum kodlarını okuyup hatanın nedenini bulmak
  • Bloklamayan ve üstel geri çekilmeli bir yeniden bağlanma döngüsü yazmak
  • RSSI değerine göre bağlantının sağlığını yorumlamak

Ders notları

Bir IoT cihazı aylarca açık kalır. Bu sürede modem yeniden başlar, elektrik kesilir, komşunun ağı kanalı doldurur. İyi bir cihaz Wi-Fi'nin kopacağını varsayar ve kendi kendine toparlanır; kötü bir cihaz while döngüsünde sonsuza kadar bekler.

Kipler

  • STA (istemci): cihaz evdeki modeme bağlanır. Sensör düğümlerinin olağan kipi.
  • AP (erişim noktası): cihaz kendi ağını yayar. İlk kurulumda telefonla bağlanıp Wi-Fi parolasını girdiğin sayfa böyle çalışır.
  • AP+STA: ikisi birlikte; kurulum sırasında hem sayfayı sunar hem ağı dener.

Durumlar

WiFi.status() bir durum kodu döndürür: WL_CONNECTED bağlı ve IP almış, WL_IDLE_STATUS deneme sürüyor, WL_DISCONNECTED bağlı değil, WL_NO_SSID_AVAIL ağ adı görünmüyor, WL_CONNECT_FAILED parola ya da kimlik doğrulama hatası. Durum kodunu günlüğe yazmak, "Wi-Fi çalışmıyor" şikâyetini "SSID görünmüyor" ya da "parola yanlış" tanısına çevirir. Arduino çekirdeği ayrıca WiFi.onEvent() ile bağlanma, IP alma ve kopma olaylarını bildirir.

Yeniden bağlanma: sabit bekleme mi, geri çekilme mi?

Elektrik kesintisinden sonra binadaki yüz cihaz aynı saniyede açılır. Hepsi her saniye yeniden denerse modem ve broker gereksiz yük altında kalır. Üstel geri çekilmede her başarısız denemeden sonra bekleme iki katına çıkar ve bir üst sınırda durur; küçük bir rastgele pay (jitter) cihazların aynı anda denemesini önler.

beklemek = min(üst sınır, taban · 2k)

Bekleme delay() ile değil, millis() karşılaştırmasıyla yapılır: döngü dönmeye devam eder, sensör okunur, yerel röle kuralları çalışır. Wi-Fi yokken de cihaz işini yapmalıdır.

RSSI

Alınan sinyal gücü dBm cinsindendir ve negatiftir. Kabaca: -50 çok iyi, -67 akış için yeterli, -75 sensör verisi için sınırda, -85 ve altı sık kopma demektir. Anteni metal kutunun içine gömmek ya da kartı toprağa yakın koymak RSSI'yi 10–20 dB düşürebilir.

Simülasyon

Wi-Fi bağlantı durumları ve yeniden bağlanma

Erişim noktası bir süre kapanır, sinyal zayıflar. Sabit beklemeyle ve üstel geri çekilmeyle yeniden bağlanmayı karşılaştır: deneme sayısı, kopuk kalınan süre ve AP geri gelince toparlanma süresi.

  • bağlı WL_CONNECTED
  • bağlanıyor WL_IDLE_STATUS
  • bekliyor WL_DISCONNECTED
  • AP yok WL_NO_SSID_AVAIL
Bağlı (1) ya da değil (0), AP kesintisi gölgeli-0.10.230.550.881.2023.947.871.795.6119.5s
Üstel geri çekilme: 6 deneme, 1 kopma, kopuk 43,2 s, AP dönünce 16,3 s'de toparlandı Sabit bekleme: 10 deneme, 1 kopma, kopuk 29,8 s, AP dönünce 2,9 s'de toparlandı
t = 30 s WiFi.status() → WL_DISCONNECTED (bekliyor)

Kod

Arduino C++: bloklamayan bağlantı ve üstel geri çekilme
#include <WiFi.h>
#include "secrets.h"        // WIFI_SSID, WIFI_PASS; dosya .gitignore'da

const uint32_t BASE_MS = 1000, CAP_MS = 30000;
uint32_t nextTry = 0;
uint8_t failures = 0;

uint32_t backoffMs(uint8_t k) {
  uint32_t w = BASE_MS << min<uint8_t>(k, 15);   // base, 2·base, 4·base…
  w = min(w, CAP_MS);
  return w / 2 + random(w / 2);                   // sarsıntı (jitter): cihazlar aynı anda denemesin
}

void wifiTask() {                                 // loop() içinden çağrılır, asla beklemez
  wl_status_t s = WiFi.status();
  if (s == WL_CONNECTED) { failures = 0; return; }
  if (millis() < nextTry) return;
  Serial.printf("status=%d, try %u\n", s, failures + 1);
  WiFi.disconnect();
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  nextTry = millis() + backoffMs(failures++);
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);                            // istemci kipi; AP kipi kurulum sayfası içindir
  WiFi.setAutoReconnect(false);                   // yeniden bağlanmayı biz yönetiyoruz
}

void loop() {
  wifiTask();
  if (WiFi.status() == WL_CONNECTED) {
    // sensör oku, yayımla; RSSI -80 dBm altındaysa uyar
    if (WiFi.RSSI() < -80) Serial.println("weak signal");
  }
}
MicroPython: durum kodları ve geri çekilme
import network, time, random
from secrets import SSID, PASSWORD   # Wokwi'de SSID = "Wokwi-GUEST", parola boş

wlan = network.WLAN(network.STA_IF)
wlan.active(True)

def connect(base=1, cap=30):
    k = 0
    while not wlan.isconnected():
        wlan.connect(SSID, PASSWORD)
        t0 = time.ticks_ms()
        while time.ticks_diff(time.ticks_ms(), t0) < 5000 and not wlan.isconnected():
            time.sleep_ms(100)
        if wlan.isconnected():
            break
        print('status', wlan.status())      # STAT_NO_AP_FOUND, STAT_WRONG_PASSWORD…
        w = min(cap, base * 2 ** k)
        time.sleep(w / 2 + random.random() * w / 2)
        k += 1
    print('ip', wlan.ifconfig()[0], 'rssi', wlan.status('rssi'))

connect()

Kendin dene

Simülasyonda erişim noktasını 20. ile 60. saniye arasında kapat. Önce sabit 1 saniyelik beklemeyi seç: kaç deneme yapıldı, kopuk kalınan süre ne kadar? Sonra üstel geri çekilmeye geç (taban 1 s, üst sınır 30 s): deneme sayısı nasıl değişti, AP geri gelince toparlanma süresi ne oldu? Sinyali -88 dBm'e indir ve kopma sayısını izle. Son olarak Wokwi'de SSID olarak "Wokwi-GUEST" ile iki kodu çalıştır ve seri monitördeki durum kodlarını oku.

Sık yapılan hatalar

  • setup() içinde while (WiFi.status() != WL_CONNECTED) ile sonsuza kadar beklemek: ağ gelmezse cihaz hiçbir iş yapmaz.
  • Tüm cihazlara aynı sabit yeniden deneme süresi vermek: kesintiden sonra hepsi aynı anda dener.
  • Wi-Fi parolasını kaynak koda yazıp depoya göndermek: secrets.h dosyası .gitignore'a girmeli.
  • Yalnız "bağlı mı" diye bakıp durum kodunu günlüğe yazmamak: sahada hatanın nedeni bulunamaz.
  • ESP32'nin 5 GHz ağa bağlanabileceğini sanmak: yalnız 2,4 GHz destekler.

Yazılım mühendisliği bağlantısı

Wi-Fi bağlantısı bir durum makinesidir: bağlanıyor, bağlı, bekliyor, AP yok. Onu açıkça modellemek test edilebilir yapar.

  • Durum geçişlerini saf bir fonksiyona koy: girdi şimdiki durum, zaman ve olay; çıktı yeni durum ve bir sonraki deneme zamanı. Simülasyon tam olarak budur.
  • Zamanı dışarıdan ver (millis() yerine parametre): birim testinde 10 dakikalık kesintiyi milisaniyede benzetirsin.
  • Gözlemlenebilirlik: deneme sayısı, son durum kodu ve RSSI periyodik olarak yayımlansın; filo panosunda zayıf cihazlar görünür.

Kendini sına

  1. Taban 1 s, üst sınır 30 s olan üstel geri çekilmede 6. başarısız denemeden sonra (k = 5) bekleme kaç saniyedir (sarsıntısız)?

  2. Üstel geri çekilme ve sarsıntının asıl amacı nedir?

  3. Seri monitörde WL_NO_SSID_AVAIL görüyorsun. Bu ne demektir?

  4. RSSI -88 dBm ölçülüyor. Bu ne anlama gelir?

Parçalar ve ilgili sayfalar

Esc
  • PanelAna sayfaSayfa
  • ModüllerTüm modüllerSayfa
  • ParçalarParça ansiklopedisiSayfa
  • Mühendislik yoluBüyükler için robotik: 128 parça, 7 seviyeSayfa
  • Robotik dersi (ESOF 323)Üniversite robotik dersi, 14 haftaSayfa
  • Drone dersiBüyükler için: parça, simülasyon, yazılım; 10 üniteSayfa
  • Blok atölyesiSerbest blok programlamaAraç
  • Devre laboratuvarıSanal Arduino ve devreAraç
  • Robot arenasıSanal robot sürüşüAraç
  • OyunlarBloklarla 8 öğretici oyunAraç
  • Mikro Kart atölyesiSanal LED kartı bloklarla programlaAraç
  • Robot atölyesiMikro Kart'ı robota tak, bloklarla görev yapAraç