Pico W: Initial Wi-Fi support (#2980)

* Pico W: Initial WiFi support: connects, but freezes after a while

* Update arduino-pico core to fix hang with Wi-Fi

* Add `picow` to workflow since it's different from `pico` now
This commit is contained in:
GUVWAF 2023-12-02 21:47:52 +01:00 committed by GitHub
parent 9e90b4af02
commit 6ff61b3e04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 154 additions and 119 deletions

View File

@ -123,6 +123,7 @@ jobs:
matrix:
include:
- board: pico
- board: picow
- board: rak11310
uses: ./.github/workflows/build_rpi2040.yml
with:

View File

@ -11,7 +11,7 @@ build_flags =
-Isrc/platform/nrf52
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/>
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/>
lib_deps=
${arduino_base.lib_deps}

View File

@ -10,6 +10,7 @@ build_src_filter =
-<platform/nrf52/>
-<platform/stm32wl/>
-<platform/rp2040>
-<mesh/wifi/>
-<mesh/http/>
-<mesh/eth/>
-<modules/esp32>

View File

@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#d2461a14ad5aa920e44508d236c2f459e3befbf8
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@ -12,7 +12,7 @@ build_flags =
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/>
lib_ignore =
BluetoothOTA

View File

@ -13,7 +13,7 @@ build_flags =
-DVECT_TAB_OFFSET=0x08000000
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
board_upload.offset_address = 0x08000000
upload_protocol = stlink

View File

@ -45,7 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef ARCH_ESP32
#include "esp_task_wdt.h"
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h"
#endif
@ -1618,12 +1618,19 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
} else if (WiFi.status() == WL_IDLE_STATUS) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
} else {
}
#ifdef ARCH_ESP32
else {
// Codes:
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
display->drawString(x, y + FONT_HEIGHT_SMALL * 1,
WiFi.disconnectReasonName(static_cast<wifi_err_reason_t>(getWifiDisconnectReason())));
}
#else
else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unkown status: " + String(WiFi.status()));
}
#endif
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));

View File

@ -32,9 +32,6 @@
#include <utility>
// #include <driver/rtc_io.h>
#include "mesh/eth/ethClient.h"
#include "mesh/http/WiFiAPClient.h"
#ifdef ARCH_ESP32
#include "mesh/http/WebServer.h"
#include "nimble/NimbleBluetooth.h"
@ -48,10 +45,12 @@ NRF52Bluetooth *nrf52Bluetooth;
#if HAS_WIFI
#include "mesh/api/WiFiServerAPI.h"
#include "mesh/wifi/WiFiAPClient.h"
#endif
#if HAS_ETHERNET
#include "mesh/api/ethServerAPI.h"
#include "mesh/eth/ethClient.h"
#endif
#include "mqtt/MQTT.h"
@ -835,11 +834,15 @@ void setup()
#ifndef ARCH_PORTDUINO
// Initialize Wifi
#if HAS_WIFI
initWifi();
#endif
#if HAS_ETHERNET
// Initialize Ethernet
initEthernet();
#endif
#endif
#ifdef ARCH_ESP32
// Start web server thread.

View File

@ -21,7 +21,7 @@
#include <pb_encode.h>
#ifdef ARCH_ESP32
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h"
#include <Preferences.h>
#include <nvs_flash.h>

View File

@ -5,7 +5,7 @@
#include "main.h"
#include "mesh/http/ContentHelper.h"
#include "mesh/http/WebServer.h"
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "mqtt/JSON.h"
#include "power.h"
#include "sleep.h"

View File

@ -1,5 +1,4 @@
#pragma once
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer);
// Declare some handler functions for the various URLs on the server

View File

@ -1,6 +1,6 @@
#include "mesh/http/ContentHelper.h"
//#include <Arduino.h>
//#include "main.h"
// #include <Arduino.h>
// #include "main.h"
void replaceAll(std::string &str, const std::string &from, const std::string &to)
{

View File

@ -2,7 +2,7 @@
#include "NodeDB.h"
#include "graphics/Screen.h"
#include "main.h"
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "sleep.h"
#include <HTTPBodyParser.hpp>
#include <HTTPMultipartBodyParser.hpp>

View File

@ -1,17 +1,22 @@
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/Periodic.h"
#include "configuration.h"
#include "main.h"
#include "mesh/api/WiFiServerAPI.h"
#include "mesh/http/WebServer.h"
#include "mqtt/MQTT.h"
#include "target_specific.h"
#include <ESPmDNS.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#ifndef ARCH_RP2040
#include "mesh/http/WebServer.h"
#include <ESPmDNS.h>
#include <esp_wifi.h>
static void WiFiEvent(WiFiEvent_t event);
#else
#include <ESP8266mDNS.h>
#endif
#ifndef DISABLE_NTP
#include <NTPClient.h>
@ -19,8 +24,6 @@
using namespace concurrency;
static void WiFiEvent(WiFiEvent_t event);
// NTP
WiFiUDP ntpUDP;
@ -44,78 +47,6 @@ Syslog syslog(syslogClient);
Periodic *wifiReconnect;
static int32_t reconnectWiFi()
{
const char *wifiName = config.network.wifi_ssid;
const char *wifiPsw = config.network.wifi_psk;
if (config.network.wifi_enabled && needReconnect) {
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
needReconnect = false;
// Make sure we clear old connection credentials
WiFi.disconnect(false, true);
LOG_INFO("Reconnecting to WiFi access point %s\n", wifiName);
delay(5000);
if (!WiFi.isConnected()) {
WiFi.begin(wifiName, wifiPsw);
}
}
#ifndef DISABLE_NTP
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
if (timeClient.update()) {
LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
struct timeval tv;
tv.tv_sec = timeClient.getEpochTime();
tv.tv_usec = 0;
perhapsSetRTC(RTCQualityNTP, &tv);
lastrun_ntp = millis();
} else {
LOG_DEBUG("NTP Update failed\n");
}
}
#endif
if (config.network.wifi_enabled && !WiFi.isConnected()) {
return 1000; // check once per second
} else {
return 300000; // every 5 minutes
}
}
bool isWifiAvailable()
{
if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
return true;
} else {
return false;
}
}
// Disable WiFi
void deinitWifi()
{
LOG_INFO("WiFi deinit\n");
if (isWifiAvailable()) {
WiFi.disconnect(true);
WiFi.mode(WIFI_MODE_NULL);
LOG_INFO("WiFi Turned Off\n");
// WiFi.printDiag(Serial);
}
}
static void onNetworkConnected()
{
if (!APStartupComplete) {
@ -158,7 +89,9 @@ static void onNetworkConnected()
syslog.enable();
}
#ifndef ARCH_RP2040
initWebServer();
#endif
initApiServer();
APStartupComplete = true;
@ -169,6 +102,89 @@ static void onNetworkConnected()
mqtt->reconnect();
}
static int32_t reconnectWiFi()
{
const char *wifiName = config.network.wifi_ssid;
const char *wifiPsw = config.network.wifi_psk;
if (config.network.wifi_enabled && needReconnect) {
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
needReconnect = false;
// Make sure we clear old connection credentials
#ifdef ARCH_ESP32
WiFi.disconnect(false, true);
#else
WiFi.disconnect(false);
#endif
LOG_INFO("Reconnecting to WiFi access point %s\n", wifiName);
delay(5000);
if (!WiFi.isConnected()) {
WiFi.begin(wifiName, wifiPsw);
}
}
#ifndef DISABLE_NTP
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
if (timeClient.update()) {
LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
struct timeval tv;
tv.tv_sec = timeClient.getEpochTime();
tv.tv_usec = 0;
perhapsSetRTC(RTCQualityNTP, &tv);
lastrun_ntp = millis();
} else {
LOG_DEBUG("NTP Update failed\n");
}
}
#endif
if (config.network.wifi_enabled && !WiFi.isConnected()) {
return 1000; // check once per second
} else {
#ifdef ARCH_RP2040
onNetworkConnected(); // will only do anything once
#endif
return 300000; // every 5 minutes
}
}
bool isWifiAvailable()
{
if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
return true;
} else {
return false;
}
}
// Disable WiFi
void deinitWifi()
{
LOG_INFO("WiFi deinit\n");
if (isWifiAvailable()) {
#ifdef ARCH_ESP32
WiFi.disconnect(true, false);
#else
WiFi.disconnect(true);
#endif
WiFi.mode(WIFI_OFF);
LOG_INFO("WiFi Turned Off\n");
// WiFi.printDiag(Serial);
}
}
// Startup WiFi
bool initWifi()
{
@ -177,10 +193,10 @@ bool initWifi()
const char *wifiName = config.network.wifi_ssid;
const char *wifiPsw = config.network.wifi_psk;
createSSLCert();
#ifndef ARCH_RP2040
createSSLCert(); // For WebServer
esp_wifi_set_storage(WIFI_STORAGE_RAM); // Disable flash storage for WiFi credentials
#endif
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
@ -189,17 +205,17 @@ bool initWifi()
getMacAddr(dmac);
snprintf(ourHost, sizeof(ourHost), "Meshtastic-%02x%02x", dmac[4], dmac[5]);
WiFi.mode(WIFI_MODE_STA);
WiFi.mode(WIFI_STA);
WiFi.setHostname(ourHost);
WiFi.onEvent(WiFiEvent);
WiFi.setAutoReconnect(true);
WiFi.setSleep(false);
if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC &&
config.network.ipv4_config.ip != 0) {
WiFi.config(config.network.ipv4_config.ip, config.network.ipv4_config.gateway, config.network.ipv4_config.subnet,
config.network.ipv4_config.dns,
config.network.ipv4_config.dns); // Wifi wants two DNS servers... set both to the same value
config.network.ipv4_config.dns);
}
#ifndef ARCH_RP2040
WiFi.onEvent(WiFiEvent);
WiFi.setAutoReconnect(true);
WiFi.setSleep(false);
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
@ -218,7 +234,7 @@ bool initWifi()
wifiDisconnectReason = info.wifi_sta_disconnected.reason;
},
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
#endif
LOG_DEBUG("JOINING WIFI soon: ssid=%s\n", wifiName);
wifiReconnect = new Periodic("WifiConnect", reconnectWiFi);
}
@ -229,6 +245,7 @@ bool initWifi()
}
}
#ifndef ARCH_RP2040
// Called by the Espressif SDK to
static void WiFiEvent(WiFiEvent_t event)
{
@ -369,6 +386,7 @@ static void WiFiEvent(WiFiEvent_t event)
break;
}
}
#endif
uint8_t getWifiDisconnectReason()
{

View File

@ -5,7 +5,7 @@
#include <Arduino.h>
#include <functional>
#ifdef ARCH_ESP32
#if defined(HAS_WIFI) && !defined(ARCH_PORTDUINO)
#include <WiFi.h>
#endif

View File

@ -1,7 +1,7 @@
#pragma once
#include "ProtobufModule.h"
#ifdef ARCH_ESP32
#include "mesh/http/WiFiAPClient.h"
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
/**

View File

@ -7,9 +7,9 @@
#include "mesh/Router.h"
#include "mesh/generated/meshtastic/mqtt.pb.h"
#include "mesh/generated/meshtastic/telemetry.pb.h"
#include "mesh/http/WiFiAPClient.h"
#include "sleep.h"
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#include <WiFi.h>
#endif
#include "mqtt/JSON.h"

View File

@ -7,7 +7,7 @@
#include "nimble/NimbleBluetooth.h"
#endif
#include "BleOta.h"
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "meshUtils.h"
#include "sleep.h"

View File

@ -11,7 +11,7 @@
#ifdef ARCH_ESP32
#include "esp32/pm.h"
#include "esp_pm.h"
#include "mesh/http/WiFiAPClient.h"
#include "mesh/wifi/WiFiAPClient.h"
#include "rom/rtc.h"
#include <driver/rtc_io.h>
#include <driver/uart.h>

View File

@ -8,8 +8,10 @@ upload_protocol = picotool
build_flags = ${rp2040_base.build_flags}
-DRPI_PICO
-Ivariants/rpipicow
-DDEBUG_RP2040_PORT=Serial
-DHW_SPI1_DEVICE
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus"
-fexceptions # for exception handling in MQTT
build_src_filter = ${rp2040_base.build_src_filter} +<mesh/wifi/>
lib_deps =
${rp2040_base.lib_deps}
${networking_base.lib_deps}

View File

@ -4,6 +4,10 @@
#define ARDUINO_ARCH_AVR
#ifndef HAS_WIFI
#define HAS_WIFI 1
#endif
#define USE_SH1106 1
// default I2C pins: